Middlewares - gro1vy/DeliverServiceAPI GitHub Wiki
ExceptionHandlingMiddleware
В методах сервисов возвращение null или любого другого индикатора неправильных входных данных не всегда говорит о проблеме, так как метод может вернуть один и тот же индикатор в разных случаях, также в контроллере приходиться писать дополнительную логику обработки значений, пришедших из метода сервиса, поэтому решено при выявлении неправильных входных данных создавать исключение и ловить их в middleware. Для этого был создан ExceptionHandlingMiddleware.
Поля класса
Помимо поля тип RequestDelegate с названием _next необходимого для переходя к следующей middleware, определено поле тип ILogger с названием _logger, которое нужно для логгирования ошибок в текстовый файл и БД. Более подробно про логгер NLog, используемый в проекте, смотреть тут.
private readonly RequestDelegate _next;
private readonly ILogger<ExceptionHandlingMiddleware> _logger;
Методы класса
В классе определены два метода InvokeAsync и HandlExceptionAsync.
Первый метод является обязательным для middleware, и в нем проиходит отлов исключений. Переход к следующей middleware в pipline обернут в try-catch, что обеспечивает отлов всех исключений, созданных в конце обработки запроса, то есть в контроллере и всех методов сервисов, которые он вызывает.
public async Task InvokeAsync(HttpContext httpContext)
{
try
{
await _next(httpContext);
}
// Отлов остальных исключений, они рассмотрены ниже
// ...
catch (Exception ex)
{
await HandlExceptionAsync(LogLevel.Critical, httpContext, ex, HttpStatusCode.InternalServerError, "Unknown error!");
}
}
Второй метод необходим для облегчения обработки исключения. Он одновременно пишет логги, используя _logger, и отправляет пользователю ответ с помощью модели ResponseDTO.
private async Task HandlExceptionAsync(LogLevel logLevel, HttpContext httpContext, Exception ex, HttpStatusCode httpStatusCode, string message)
{
_logger.Log(logLevel, ex, ex.Message);
HttpResponse response = httpContext.Response;
response.ContentType = "application/json";
response.StatusCode = (int)httpStatusCode;
var errorDTO = new ResponseDTO()
{
Message = message,
Status = (int)httpStatusCode
};
await response.WriteAsJsonAsync(errorDTO);
}
Обрабатываемые исключения В try-cath попадают все исключения, которые сгенерирует приложения благодаря тому, что самый последний блок ловит Exception, который логгируется с уровнем Critical. Помимо него есть и другие исключения, которые выбрасываются методами asp.net и которые выбрасываются сервисами нашего приложения.
Исключения выбрасываемые ASP.NET
Все следующие исключения при отправке клиенту ответа имеют статус код 500:
- InvalidOperationException логгируется с уровнем Error и отправляет клиенту сообщение "Operation execution error!"
- OperationCanceledException логгируется с уровнем Error и отправляет клиенту сообщение "The operation was canceled!"
- EncoderFallbackException логгируется с уровнем Error и отправляет клиенту сообщение "Text encoding error!"
- ArgumentException логгируется с уровнем Error и отправляет клиенту сообщение "Unknown error!"
- SaltParseException логгируется с уровнем Error и отправляет клиенту сообщение "Password verification error!"
- DbUpdateException логгируется с уровнем Error и отправляет клиенту сообщение "An error occurred while saving the data. Please try again later."
- FormatException логгируется с уровнем Error и отправляет клиенту сообщение "Data format error"
- SecurityTokenEncryptionFailedException логгируется с уровнем Warning и отправляет клиенту сообщение "Error processing a secure token!"
- RuntimeBinderException логгируется с уровнем Error и отправляет клиенту сообщение "Unknown error!"
Исключения выбрасываемые приложением:
- ValidationProblemException логгируется с уровнем Info и отправляет клиенту сообщение из исключения. Имеет статус код 400
- BadRequestException логгируется с уровнем Info и отправляет клиенту сообщение из исключения. Имеет статус код 400
- NotFoundException логгируется с уровнем Info и отправляет клиенту сообщение из исключения. Имеет статус код 404