Обработка ошибок в ASP.NET Core. UseDeveloperExceptionPage и UseExceptionHandler

Даже идеально протестированное и отлаженное приложение не избавляется от всех возможных исключительных ситуаций на 100% и приложения ASP.NET Core здесь не исключение. Условно, все возможные ошибки в ASP.NET Core можно разделить на ошибки в приложении (деление на ноль, доступ к несуществующему объекту и т.д.) и ошибки протокола HTTP (ошибки сервера с кодом 5хх, ошибки с кодом 4хх). Для обработки этих ошибок могут использоваться различные средства.

UseDeveloperExceptionPage

Для обработки исключений в приложении, находящимся в процессе разработки, предназначен компонент middleware — DeveloperExceptionPageMiddleware, который мы можем включить в конвейер обработки запросов, выполнив UseDeveloperExceptionPage(). Этот компонент включается в конвейер обработки запроса автоматически и при возникновении какой-либо ошибки в приложении генерирует специальную страницу с подробным описанием ошибки. Например, рассмотрим следующее приложение:

public static void Main(string[] args)
{
   var builder = WebApplication.CreateBuilder(args);
   var app = builder.Build();

   app.Run(async (context) =>
    {
        int a = 0;
        await context.Response.WriteAsync($"{10/a}");
    });
    app.Run();
}

здесь в middleware производится попытка деления на ноль. Если запустить это приложение, то мы увидим действие DeveloperExceptionPageMiddleware:

Следует отметить, что DeveloperExceptionPageMiddleware включается в конвейер по умолчанию только для стадии разработки, т.е. когда имя среды окружения «Development» в рабочей версии приложения пользователь увидит следующее:

то есть, по умолчанию, всё, что может знать пользователь — это то, что на сервере произошла ошибка. Что это за ошибка, кто виноват и что делать — об этом ASP.NET Core по умолчанию пользователя не информирует. Однако, мы можем сделать это самостоятельно, используя следующий компонент middleware.

UseExceptionHandler

Метод UseExceptionHandler добавляет в конвейер обработки запросов компонент middleware ExceptionHandlerMiddleware, который, в случае возникновения ошибки перенаправляет пользователя на заданную страницу и уже на этой странице мы можем каким-либо образом проинформировать пользователя. Например:

app.Environment.EnvironmentName = "Production"; // меняем имя окружения

if (app.Environment.IsDevelopment()==false)
{
    app.UseExceptionHandler("/error");
}

//страница обработки ошибки
app.MapGet("/error", () => "Error");

Если в рабочем варианте приложения возникнет ошибка, то пользователю будет выдана строка «Error»:

вторая версия метода UseExceptionHandler принимает IApplicationBuilder, что позволяет сделать следующую обработку исключения:

if (app.Environment.IsDevelopment()==false)
{
    app.UseExceptionHandler(application => 
    {
        application.Run(async (context) => 
        {
            context.Response.StatusCode = 500;
            await context.Response.WriteAsync("Error");
        });
    });
}

Результат работы приложения будет тот же, но, при этом, пользователь уже не сможет перейти на страницу «/error» просто набрав её адрес в браузере.

С выводом информации об ошибке пользователю разобрались, но при этом, возникает следующий вопрос: как детализировать информацию об ошибке? Просто выдавать «Error» не самая хороша идея. В ASP.NET Core мы можем получить доступ к исключению, используя свойство HttpContext.Features

 Получение доступа к исключению

Чтобы получить доступ к исключению и к пути исходного запроса в обработчике ошибок ASP.NET Core использует специальный интерфейс IExceptionHandlerPathFeature. Запросить объект, реализующий интерфейс мы можем, воспользовавшись свойством HttpContext.Features. Детализируем сообщение об ошибке следующим образом:

if (app.Environment.IsDevelopment()==false)
{
    app.UseExceptionHandler((app) => 
    {
        app.Run(async(context) => 
        {
            //пытаемся получить информацию об исключении
            var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
            if (exceptionHandlerPathFeature != null)
               await context.Response.WriteAsync($"Error: {exceptionHandlerPathFeature.Error.Message}");
            else
                await context.Response.WriteAsync($"Unknown Error");
        });
    });
}

Теперь, если мы сможем получить информацию об ошибке — она будет выведена пользователю, иначе — будет выводиться строка «Unknown Error». Например,

Вообще, IExceptionHandlerPathFeature содержит следующие свойства:

Endpoint Возвращает объект , представляющий endpoint для исходного запроса
Error Ошибка, обнаруженная во время исходного запроса
Path Часть пути запроса, которая идентифицирует запрошенный ресурс.
RouteValues Возвращает объект RouteValueDictionary, связанный с исходным запросом

Используя эти свойства можно максимально детализировать сообщение об ошибке пользователю.

Итого

Обработка ошибок в ASP.NET Core может происходить по-разному, в зависимости от среды окружения. Так, если приложение находится в стадии разработки, то при возникновении ошибки срабатывает DeveloperExceptionPageMiddleware, который генерирует максимально подробную информацию об ошибке для разработчика. Если же приложение вышло из стадии разработки, то информировать пользователя об ошибке можно, используя компонент middleware ExceptionHandlerMiddleware, который необходимо подключить как можно ближе к началу конвейера обработки запросов.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии