75 lines
3.3 KiB
C#
75 lines
3.3 KiB
C#
using Microsoft.AspNetCore.Diagnostics;
|
|
using PARR.API.Contracts.V1.Responses.Base;
|
|
using PARR.Domain.Exceptions;
|
|
|
|
namespace PARR.API.Infrastructure.Middleware
|
|
{
|
|
/// <summary>
|
|
/// Глобальная обработка ошибок согласно моих кастомных Exception
|
|
/// </summary>
|
|
public class GlobalExceptionHandler : IExceptionHandler
|
|
{
|
|
private readonly ILogger<GlobalExceptionHandler> logger;
|
|
|
|
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
|
|
{
|
|
this.logger = logger;
|
|
}
|
|
|
|
public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
|
|
{
|
|
logger.LogError(exception, "Ошибка во время запроса {TraceId}: {Message}", httpContext.TraceIdentifier, exception.Message);
|
|
|
|
// определяем статус код, в зависимости от типа исключения
|
|
|
|
var statusCode = exception switch
|
|
{
|
|
NotFoundException => StatusCodes.Status404NotFound,
|
|
DbErrorException => StatusCodes.Status502BadGateway,
|
|
ExternalServiceException => StatusCodes.Status502BadGateway,
|
|
AppValidationException => StatusCodes.Status400BadRequest,
|
|
FluentValidation.ValidationException => StatusCodes.Status400BadRequest,
|
|
AlreadyExistsException => StatusCodes.Status409Conflict,
|
|
UnauthorizedException => StatusCodes.Status401Unauthorized,
|
|
ForbiddenException => StatusCodes.Status403Forbidden,
|
|
NextRunException => StatusCodes.Status422UnprocessableEntity,
|
|
//todo: ---------- другие ошибки ----------
|
|
_ => StatusCodes.Status500InternalServerError
|
|
};
|
|
|
|
// Для критических серверных ошибок (5xx) пишем детальный лог
|
|
if (statusCode >= 500)
|
|
{
|
|
logger.LogError(exception, "Критическая ошибка сервера: {Message}", exception.Message);
|
|
}
|
|
|
|
//var errorMessage = exception.Message;
|
|
var errors = new List<ErrorModel>();
|
|
|
|
// Если это ошибка FluentValidatioun, вытаскиваем детали по каждому полю
|
|
if (exception is FluentValidation.ValidationException fluentEx)
|
|
{
|
|
// ошибка валидации, вернем по каждому полю
|
|
foreach (var error in fluentEx.Errors)
|
|
{
|
|
errors.Add(new ErrorModel { FieldName = error.PropertyName, Message = error.ErrorMessage });
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// это не ошибка валидации, вернем сообщение
|
|
errors.Add(new ErrorModel { Message = exception.Message });
|
|
}
|
|
|
|
httpContext.Response.StatusCode = statusCode;
|
|
|
|
var response = new Response<object?>(null, false, errors, exception.Message);
|
|
|
|
await httpContext.Response.WriteAsJsonAsync(response, cancellationToken);
|
|
|
|
// ошибка обработана
|
|
return true;
|
|
}
|
|
}
|
|
}
|