MidПрактика1 min

Шаг 18: Обработка ошибок (Middleware)

Глобальный ExceptionHandlingMiddleware: маппинг исключений на HTTP-коды, ProblemDetails формат, подключение в pipeline

Шаг 18: Обработка ошибок

Middleware оборачивает весь pipeline в try-catch и преобразует исключения в структурированные HTTP-ответы.

ExceptionHandlingMiddleware.cs

В папке Middleware проекта API:

using FluentValidation;
using OrderManagement.Domain.Exceptions;

namespace OrderManagement.API.Middleware;

public class ExceptionHandlingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<ExceptionHandlingMiddleware> _logger;

    public ExceptionHandlingMiddleware(
        RequestDelegate next,
        ILogger<ExceptionHandlingMiddleware> logger)
    { _next = next; _logger = logger; }

    public async Task InvokeAsync(HttpContext context)
    {
        try { await _next(context); }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error: {Message}", ex.Message);
            await HandleExceptionAsync(context, ex);
        }
    }

    private static async Task HandleExceptionAsync(
        HttpContext context, Exception exception)
    {
        var (statusCode, title) = exception switch
        {
            OrderNotFoundException => (404, "Not found"),
            DomainException => (400, "Business rule violation"),
            ValidationException => (400, "Validation error"),
            _ => (500, "Internal server error")
        };

        var response = new
        {
            status = statusCode,
            title,
            detail = exception.Message,
            errors = exception is ValidationException vex
                ? vex.Errors.Select(e => new
                    { property = e.PropertyName,
                      message = e.ErrorMessage })
                : null
        };

        context.Response.StatusCode = statusCode;
        context.Response.ContentType = "application/json";
        await context.Response.WriteAsJsonAsync(response);
    }
}

Подключение в Program.cs

Добавьте строку перед app.MapControllers():

using OrderManagement.API.Middleware;

app.UseMiddleware<ExceptionHandlingMiddleware>();
app.MapControllers();

DomainException -> HTTP 400, OrderNotFoundException -> HTTP 404, ValidationException -> HTTP 400 со списком ошибок, всё остальное -> HTTP 500.

Проверь себя

Почему OrderNotFoundException маппится на 404, а DomainException на 400?

Что такое switch expression в C#?

Что такое Middleware в ASP.NET Core?