Как Обрабатывать Необработанные Исключения В Веб-Api Asp.net Core

Чтобы обработка исключений была простой и последовательной, старайтесь не создавать исключения в тех случаях, когда вы можете определить ошибку самостоятельно.

Я рекомендую вернуть подходящую ошибку, как в приведенном ниже коде.

  
  
  
  
   

[HttpGet("{id:int}")] public async Task<ActionResult<Order>> Get(int id, CancellationToken cancellationToken) { var order = await _ordersService.Get(id, cancellationToken); if (order == null) { return NotFound(); } return Ok(order); }

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

Использование исключений снижает производительность, отрицательно влияет на читаемость кода, нарушает поток прерываний и требует дополнительных действий для правильной обработки исключений.

Также избегайте пребывания в состоянии API, где выдача исключения и отправка ошибки 500 — единственный способ ответить на запрос.

Такие ситуации должны стать поводом для рефакторинга вашего API и вариантов использования.

Отправляйте ошибку 500 только в исключительных необработанных случаях, таких как проблемы с базой данных, системные ошибки и т. д. Существует несколько способов добавить обработку исключений в ASP.NET Core. Этот Фильтры исключений , Лямбда-обработчик исключений И Промежуточное ПО .

Я рекомендую последнее.

Промежуточное программное обеспечение улавливает ошибки конструкторов контроллеров, фильтров и обработчиков, ошибки маршрутизации и т. д. Реализуйте интерфейс IMiddleware и зарегистрируйте этот класс в Startup.cs, как показано в коде ниже.

Обработчик ошибок должен первым в конвейере перехватывать любые исключения при обработке запроса.



public class Startup { public void ConfigureServices(IServiceCollection services) { // Middlewares services.AddTransient<ErrorHandlerMiddleware>(); services.AddTransient<YourCustomMiddleware>(); services.AddControllers(); } public void Configure(IApplicationBuilder app) { app.UseMiddleware<ErrorHandlerMiddleware>(); // Should be always in the first place app.UseRouting(); app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); app.UseMiddleware<YourCustomMiddleware>(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } }

Если исключение не будет обработано, клиенты API получат неизвестную ошибку.

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

В приведенном ниже коде добавляется класс C#, который выполняет все вышеперечисленное.



public class ErrorHandlerMiddleware : IMiddleware { private readonly ILogger<ErrorHandlerMiddleware> _logger; public ErrorHandlerMiddleware(ILogger<ErrorHandlerMiddleware> logger) { _logger = logger; } public async Task InvokeAsync(HttpContext context, RequestDelegate next) { try { await next(context); } catch (Exception exception) { const string message = "An unhandled exception has occurred while executing the request."; _logger.LogError(exception, message); context.Response.Clear(); context.Response.StatusCode = StatusCodes.Status500InternalServerError; } } }

Я уверен, что нет необходимости проверять свойство context.Response.HasStarted. .

NET сам справляется с этим довольно хорошо, выдавая исключение InvalidOperationException с подробным сообщением.

Как это выглядит в консоли в нашем случае:

Как обрабатывать необработанные исключения в веб-API ASP.NET Core

Этого достаточно? В моих проектах обычно немного больше требований к обработке ошибок.

Вот они:

  1. Запишите более подробную информацию об исключении.

    Не добавляйте эту информацию в сообщение об исключении.

    (Вы можете прочитать о том, как использовать свойство Exception.Data для регистрации дополнительной информации об исключениях.

    в моей предыдущей статье .

    )

  2. Не отправляйте клиентам веб-API конфиденциальную внутреннюю информацию, такую как трассировка стека, данные исключений и т. д.
  3. Не рассматривайте TaskCanceledException как внутреннюю ошибку сервера, если исключение вызвано отменой запроса клиентом, поэтому наиболее подходящим ответом HTTP в этом случае будет 499.
  4. Используйте JSON как наиболее подходящий веб-формат для обработки ошибок на стороне клиента.

  5. Текст ошибки переведен на другие языки, поэтому лучше не показывать пользователю сообщение об исключении.

    Это должно быть что-то, что можно легко перевести, например: «О! Что-то пошло не так».

    Также сообщение должно содержать какой-то уникальный код, с помощью которого пользователь сможет обратиться в службу поддержки вашего приложения.

  6. Используйте систему мониторинга для хранения, анализа журналов, поиска и агрегирования проблем на основе данных об ошибках, включая коды ошибок.

    Это создаст возможности для дальнейшей автоматизации поддержки вашего приложения.

Ниже приведен пример более сложного обработчика ошибок, соответствующего этим требованиям.



public class ErrorHandlerMiddleware : IMiddleware { private static readonly JsonSerializerOptions SerializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) }, WriteIndented = true }; private readonly IWebHostEnvironment _env; private readonly ILogger<ErrorHandlerMiddleware> _logger; public ErrorHandlerMiddleware(IWebHostEnvironment env, ILogger<ErrorHandlerMiddleware> logger) { _env = env; _logger = logger; } public async Task InvokeAsync(HttpContext context, RequestDelegate next) { try { await next(context); } catch (Exception exception) when (context.RequestAborted.IsCancellationRequested) { const string message = "Request was cancelled"; _logger.LogInformation(message); _logger.LogDebug(exception, message); context.Response.Clear(); context.Response.StatusCode = 499; //Client Closed Request } catch (Exception exception) { exception.AddErrorCode(); const string message = "An unhandled exception has occurred while executing the request."; _logger.LogError(exception, exception is YourAppException ? exception.Message : message); const string contentType = "application/json"; context.Response.Clear(); context.Response.StatusCode = StatusCodes.Status500InternalServerError; context.Response.ContentType = contentType; var json = ToJson(exception); await context.Response.WriteAsync(json); } } private string ToJson(in Exception exception) { var message = exception.Message; var code = exception.GetErrorCode(); if (!_env.IsDevelopmentOrQA()) { return JsonSerializer.Serialize(new { message, code }, SerializerOptions); } try { var info = exception.ToString(); var data = exception.Data; var error = new { message, code, info, data }; return JsonSerializer.Serialize(error, SerializerOptions); } catch (Exception ex) { const string mes = "An exception has occurred while serializing error to JSON"; _logger.LogError(ex, mes); } return string.Empty; } }

Я предлагаю использовать хэш-код исключения в качестве кода ошибки, чтобы отправлять пользователям тот же код для решения аналогичных проблем.

Для создания шорткода подойдет любой алгоритм хеширования.

Я применяю наиболее доступный SHA-1, а затем усекаю результат до длины, достаточной для сохранения уникальности кода ошибки.

Расширение класса Exception, которое выдает короткий код ошибки, добавляется с использованием приведенного ниже кода.



private const string ErrorCodeKey = "errorCode"; public static Exception AddErrorCode(this Exception exception) { using var sha1 = SHA1.Create(); var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(exception.ToString())); var errorCode = string.Concat(hash[.

5].

Select(b => b.ToString("x"))); exception.Data[ErrorCodeKey] = errorCode; return exception; } public static string GetErrorCode(this Exception exception) { return (string)exception.Data[ErrorCodeKey]; }

Простой пример всплывающего окна с ошибкой на стороне клиента.



Как обрабатывать необработанные исключения в веб-API ASP.NET Core

Я надеюсь, что этот подход поможет вам с поддержкой приложений.

Буду благодарен за ваши вопросы и комментарии к статье :) Теги: #программирование #C++ #.

NET #asp.net core #ASP.NET #ASP #ASP #error #Exception #middleware #webapi #handling

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.