Глобальная обработка исключений
Я использую в проекте глобальную обработку исключений. Проблема в том, что некоторые исключения не доходят до обработчика и обрабатываются раньше из-за чего я не могу подкорректировать response. Например, я делаю ошибку при запросе, где специально указываю пустое значению ключу или указываю слишком большое значение для переменной из-за чего происходит переполнение. После JsonSerializer при попытке сериализовать в DTO выдаёт, допустим, вот такое исключение: "The JSON value could not be converted to System.UInt16". Я ожидаю, что это исключение попадёт в метод HandleExceptionAsync(HttpContext context, Exception exception), но до этого метода ничего не доходит, исключение обрабатывается раньше и отсылается как есть. При это другие ексепшены он ловит, например, от FluentValidation или деление на ноль.
Код CustomExceptionHandlerMiddleware:
using System.Net;
using System.Text.Json;
using FluentValidation;
using Company.Application.Common.Exceptions;
namespace TransportPetrus.WebAPI.Middleware
{
public class CustomExceptionHandlerMiddleware
{
private readonly RequestDelegate _next;
public CustomExceptionHandlerMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception exception)
{
await HandleExceptionAsync(context, exception);
}
}
private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
var code = HttpStatusCode.InternalServerError;
var result = string.Empty;
switch (exception)
{
case ValidationException validationException:
code = HttpStatusCode.BadRequest;
result = JsonSerializer.Serialize(validationException.Errors.Select(error => error.PropertyName + " - " + error.ErrorMessage));
break;
case NotFoundException:
code = HttpStatusCode.NotFound;
break;
}
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)code;
if (result == string.Empty)
{
result = JsonSerializer.Serialize(new { error = exception.Message }); //тут я планирую подредактивровать response
}
await context.Response.WriteAsync(result);
}
}
}
Program.cs код
using Company.Application;
using Company.Application.Common.Mapping;
using Company.Persistence;
using Company.WebAPI.Middleware;
using System.Reflection;
namespace Company.WebAPI
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddPersistence(builder.Configuration);
using (var scope = builder.Services.BuildServiceProvider().CreateScope())
{
var serviceProvider = scope.ServiceProvider;
try
{
var context = serviceProvider.GetRequiredService<CompanyDbContext>();
DbInitializer.Initialize(context);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
builder.Services.AddAutoMapper(config =>
{
config.AddProfile(new AssambleMappingProfile(Assembly.GetExecutingAssembly()));
config.AddProfile(new AssambleMappingProfile(typeof(CompanyDbContext).Assembly));
});
builder.Services.AddCors(config =>
{
config.AddPolicy("AllowAll", policy =>
{
policy.AllowAnyHeader();
policy.AllowAnyMethod();
policy.AllowAnyOrigin();
});
});
builder.Services.AddApplication();
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
var app = builder.Build();
app.UseCustomExceptionHandler();
app.UseRouting();
app.UseHttpsRedirection();
app.UseCors("AllowAll");
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
}
}
Пример запроса Postman:
{
"CargoType": "Какой-то тип груза",
"ShippingPort" : "Какой-то порт",
"ContainerType" : "Какой-то контейнер",
"DeliveryPlace" : "Какое-то место доставки",
"PackagingType" : "Какая-то упаковка",
"CustomsClearance" : "Какой-то таможенное оформление",
"TranshipmentPort" : "Какой-то порт перевалки",
"DeliveryConditions" : "Какие-то условия доставки",
"DeadlineProvidingCP" : "Какой-то срок предоставления кп",
"CargoReadinessPeriod" : "Какая-то готовность груза",
"RatePerContainer" : "12",
"DollarExchangeRate" : "1",
"RatePerTon" : "1",
"WeightOnePiece" : "1",
"LoadingPerContainerGross": "2222222", //Будет вызвано переполнение
"LoadingPerContainerNet" : "3",
"PlacesInContainer" : "2",
"NumberOfContainers" : "2",
"Note" : ""
}
Ответ Postman:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"createRequestTransportationRateDto": [
"The createRequestTransportationRateDto field is required."
],
"$.LoadingPerContainerGross": [
"The JSON value could not be converted to System.UInt16. Path: $.LoadingPerContainerGross | LineNumber: 15 | BytePositionInLine: 41."
]
},
"traceId": "00-3415b33b737a06577c6dca7b2abb6239-339a2df72d7763eb-00"
}
Ответ я хочу отредактировать и убрать лишнее.