Przejdź do treści

TailoredApps.Shared.ExceptionHandling

NuGet License: MIT


Opis

Biblioteka standaryzuje obsługę wyjątków w aplikacjach ASP.NET Core Web API. Rozwiązuje problem niespójnych odpowiedzi błędów — zamiast nieobrobionych stack traces lub przypadkowych formatów JSON, każdy błąd jest konwertowany na ujednoliconą strukturę ExceptionOrValidationError.

Dostarcza dwa mechanizmy:

  • Middleware (ConfigureExceptionHandler) — globalny handler przechwytujący wyjątki dla całej aplikacji
  • Action Filter (HandleExceptionAttribute) — dekoracyjne podejście na poziomie kontrolera/akcji

Możesz zdefiniować własny IExceptionHandlingProvider, który mapuje konkretne typy wyjątków na kody HTTP i komunikaty błędów.


Instalacja

dotnet add package TailoredApps.Shared.ExceptionHandling

Rejestracja w DI

// Program.cs
using TailoredApps.Shared.ExceptionHandling.WebApiCore;

// Rejestracja serwisu + własnego handlera
builder.Services
    .AddExceptionHandlingForWebApi<IExceptionHandlingProvider, MyExceptionHandlingProvider>();

// Opcja A: Globalny filter MVC
builder.Services.AddControllers(options =>
{
    options.Filters.AddExceptionHAndlingFilterAttribute();
});

// Opcja B: Middleware (preferowane dla globalnej obsługi)
var app = builder.Build();
app.ConfigureExceptionHandler();

Przykład użycia

Własny provider mapujący wyjątki

using TailoredApps.Shared.ExceptionHandling.Interfaces;
using TailoredApps.Shared.ExceptionHandling.Model;

public class MyExceptionHandlingProvider : IExceptionHandlingProvider
{
    public ExceptionHandlingResponse Response(Exception exception)
    {
        return exception switch
        {
            ValidationException validationEx => new ExceptionHandlingResponse
            {
                ErrorCode = 422,
                Errors = validationEx.Errors
                    .Select(e => new ExceptionOrValidationError(e.PropertyName, e.ErrorMessage))
                    .ToList()
            },

            NotFoundException notFoundEx => new ExceptionHandlingResponse
            {
                ErrorCode = 404,
                Errors = new[] { new ExceptionOrValidationError("", notFoundEx.Message) }
            },

            UnauthorizedException => new ExceptionHandlingResponse
            {
                ErrorCode = 401,
                Errors = new[] { new ExceptionOrValidationError("", "Unauthorized") }
            },

            _ => new ExceptionHandlingResponse
            {
                ErrorCode = 500,
                Errors = new[] { new ExceptionOrValidationError("", "Internal server error") }
            }
        };
    }
}

Wynikowy format JSON odpowiedzi błędu

{
  "errors": [
    {
      "field": "Email",
      "message": "Email address is required"
    },
    {
      "message": "Name must not be empty"
    }
  ]
}

Właściwość field jest pomijana (serializacja WhenWritingNull) gdy błąd nie dotyczy konkretnego pola.


API Reference

Typ Rodzaj Opis
ExceptionOrValidationError Klasa Model błędu: Field (nullable) + Message
IExceptionHandlingProvider Interfejs Mapuje Exception na ExceptionHandlingResponse
IExceptionHandlingService Interfejs Wyższy poziom — wywołuje provider i zwraca response
ExceptionHandlingConfiguration.AddExceptionHandlingForWebApi Metoda ext. Rejestruje handler + filter w DI
ExceptionMiddlewareExtensions.ConfigureExceptionHandler Metoda ext. Dodaje middleware do pipeline
HandleExceptionAttribute Action Filter Dekoracyjna obsługa wyjątku na poziomie akcji
ExceptionHandlingResponse Klasa Wynikowy obiekt: ErrorCode (HTTP) + Errors (lista)

🤖 AI Agent Prompt

## TailoredApps.Shared.ExceptionHandling — Instrukcja dla agenta AI

Używasz biblioteki TailoredApps.Shared.ExceptionHandling do standaryzacji błędów API.

### Rejestracja
```csharp
builder.Services.AddExceptionHandlingForWebApi<IExceptionHandlingProvider, MyProvider>();
// Opcja A - middleware (globalnie):
app.ConfigureExceptionHandler();
// Opcja B - filter MVC:
builder.Services.AddControllers(o => o.Filters.AddExceptionHAndlingFilterAttribute());

Implementacja własnego providera

public class MyProvider : IExceptionHandlingProvider
{
    public ExceptionHandlingResponse Response(Exception ex) => ex switch
    {
        NotFoundException => new() { ErrorCode = 404, Errors = [new("", ex.Message)] },
        ValidationException ve => new() { ErrorCode = 422, Errors = ve.Errors
            .Select(e => new ExceptionOrValidationError(e.PropertyName, e.ErrorMessage)).ToList() },
        _ => new() { ErrorCode = 500, Errors = [new("", "Internal server error")] }
    };
}

Format odpowiedzi

{ "errors": [{ "field": "Email", "message": "Required" }, { "message": "Global error" }] }

Zasady

  • ExceptionOrValidationError z pustym field (string.Empty) → pole Field = null w JSON (pomijane)
  • Zawsze implementuj własny IExceptionHandlingProvider mapujący domeny wyjątki
  • Middleware ConfigureExceptionHandler obsługuje WSZYSTKIE wyjątki — filter tylko opakowane ```