Udostępnij za pomocą


Obsługa błędów w interfejsach API platformy ASP.NET Core

Uwaga / Notatka

Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z aktualną wersją, zobacz artykuł w wersji .NET 10.

Ostrzeżenie

Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz zasady pomocy technicznej platformy .NET i platformy .NET Core. Aby zapoznać się z bieżącą wersją, przeczytaj artykuł w wersji .NET 9.

W tym artykule opisano sposób obsługi błędów w interfejsach API platformy ASP.NET Core. Wybrano dokumentację dla minimalnych interfejsów API. Aby wyświetlić dokumentację interfejsów API opartych na kontrolerach, wybierz kartę Kontrolery. Aby uzyskać Blazor wskazówki dotyczące obsługi błędów, zobacz Obsługa błędów w aplikacjach platformy ASP.NET CoreBlazor.

Strona wyjątku dla deweloperów

Na stronie wyjątku dewelopera są wyświetlane szczegółowe informacje o nieobsługiwanych wyjątkach żądań. Używa DeveloperExceptionPageMiddleware go do przechwytywania synchronicznych i asynchronicznych wyjątków z potoku HTTP i generowania odpowiedzi o błędach. Strona wyjątku dla deweloperów jest uruchamiana na wczesnym etapie potoku oprogramowania pośredniczącego, dzięki czemu może przechwytywać nieobsługiwane wyjątki zgłaszane w następujący sposób oprogramowania pośredniczącego.

aplikacje ASP.NET Core domyślnie włączają stronę wyjątku dla deweloperów, gdy obie te aplikacje:

Aplikacje utworzone przy użyciu wcześniejszych szablonów, czyli przy użyciu metody WebHost.CreateDefaultBuilder, mogą włączyć stronę wyjątku dla deweloperów, wywołując metodę app.UseDeveloperExceptionPage.

Ostrzeżenie

Nie włączaj strony wyjątku dla deweloperów, chyba że aplikacja jest uruchomiona w środowisku dewelopera. Nie udostępniaj publicznie szczegółowych informacji o wyjątkach, gdy aplikacja działa w środowisku produkcyjnym. Aby uzyskać więcej informacji na temat konfigurowania środowisk, zobacz ASP.NET Podstawowe środowiska uruchomieniowe.

Strona wyjątku dewelopera może zawierać następujące informacje o wyjątku i żądaniu:

  • Ślad stosu
  • Parametry ciągu zapytania, jeśli istnieją
  • Pliki cookie, jeśli istnieją
  • Nagłówki
  • Metadane punktu końcowego, jeśli istnieją

Strona wyjątku dla deweloperów nie jest gwarantowana, aby podać żadne informacje. Użyj rejestrowania, aby uzyskać pełne informacje o błędzie.

Na poniższej ilustracji przedstawiono przykładową stronę wyjątku dla deweloperów z animacją, aby wyświetlić karty i wyświetlane informacje:

Animowana strona wyjątku dla deweloperów, aby wyświetlić każdą wybraną kartę.

W odpowiedzi na żądanie z nagłówkiem Accept: text/plain strona wyjątku dewelopera zwraca zwykły tekst zamiast HTML. Przykład:

Status: 500 Internal Server Error
Time: 9.39 msSize: 480 bytes
FormattedRawHeadersRequest
Body
text/plain; charset=utf-8, 480 bytes
System.InvalidOperationException: Sample Exception
   at WebApplicationMinimal.Program.<>c.<Main>b__0_0() in C:\Source\WebApplicationMinimal\Program.cs:line 12
   at lambda_method1(Closure, Object, HttpContext)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

HEADERS
=======
Accept: text/plain
Host: localhost:7267
traceparent: 00-0eab195ea19d07b90a46cd7d6bf2f

Aby wyświetlić stronę wyjątku dla deweloperów w minimalnym interfejsie API:

W tej sekcji opisano następującą przykładową aplikację, aby zademonstrować sposoby obsługi wyjątków w minimalnym interfejsie API. Zgłasza wyjątek w przypadku żądania punktu końcowego /exception :

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/exception", () => 
{
    throw new InvalidOperationException("Sample Exception");
});

app.MapGet("/", () => "Test by calling /exception");

app.Run();

Procedura obsługi wyjątków

W środowiskach nieprodukcyjnych użyj oprogramowania pośredniczącego obsługi wyjątków , aby wygenerować ładunek błędu.

Aby skonfigurować metodę , wywołaj metodę Exception Handler MiddlewareUseExceptionHandler. Na przykład poniższy kod zmienia aplikację w odpowiedzi na ładunek zgodny ze specyfikacją RFC 7807 do klienta. Aby uzyskać więcej informacji, zobacz sekcję Szczegóły problemu w dalszej części tego artykułu.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseExceptionHandler(exceptionHandlerApp 
    => exceptionHandlerApp.Run(async context 
        => await Results.Problem()
                     .ExecuteAsync(context)));

app.MapGet("/exception", () => 
{
    throw new InvalidOperationException("Sample Exception");
});

app.MapGet("/", () => "Test by calling /exception");

app.Run();

Odpowiedzi na błędy klienta i serwera

Rozważmy następującą minimalną aplikację interfejsu API.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/users/{id:int}", (int id) 
    => id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)));

app.MapGet("/", () => "Test by calling /users/{id:int}");

app.Run();

public record User(int Id);

Punkt /users końcowy tworzy 200 OK z reprezentacją jsonUser wartości , gdy id jest większa niż 0, w przeciwnym razie 400 BAD REQUEST kod stanu bez treści odpowiedzi. Aby uzyskać więcej informacji na temat tworzenia odpowiedzi, zobacz Tworzenie odpowiedzi w minimalnych aplikacjach interfejsu API.

Można Status Code Pages middleware je skonfigurować tak, aby tworzyła wspólną zawartość treści, gdy jest pusta, dla wszystkich odpowiedzi klienta HTTP (400-499) lub serwera ().500 -599 Oprogramowanie pośredniczące jest konfigurowane przez wywołanie metody rozszerzenia UseStatusCodePages .

Na przykład w poniższym przykładzie aplikacja zmienia odpowiedź na ładunek zgodny ze specyfikacją RFC 7807 do klienta dla wszystkich odpowiedzi klienta i serwera, w tym błędy routingu (na przykład 404 NOT FOUND). Aby uzyskać więcej informacji, zobacz sekcję Szczegóły problemu .

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseStatusCodePages(async statusCodeContext 
    => await Results.Problem(statusCode: statusCodeContext.HttpContext.Response.StatusCode)
                 .ExecuteAsync(statusCodeContext.HttpContext));

app.MapGet("/users/{id:int}", (int id) 
    => id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)) );

app.MapGet("/", () => "Test by calling /users/{id:int}");

app.Run();

public record User(int Id);

Szczegóły problemu

Szczegóły problemu nie są jedynym formatem odpowiedzi opisujący błąd interfejsu API HTTP, jednak są one często używane do zgłaszania błędów dla interfejsów API HTTP.

Usługa szczegółów problemu IProblemDetailsService implementuje interfejs, który obsługuje tworzenie szczegółów problemu w ASP.NET Core. Metoda AddProblemDetails(IServiceCollection) rozszerzenia w systemie IServiceCollection rejestruje domyślną IProblemDetailsService implementację.

W aplikacjach ASP.NET Core następujące oprogramowanie pośredniczące generuje szczegóły problemów odpowiedzi HTTP, gdy AddProblemDetails jest wywoływana, z wyjątkiem sytuacji, gdy Accept nagłówek HTTP żądania nie zawiera jednego z typów zawartości obsługiwanych przez zarejestrowane IProblemDetailsWriter (domyślnie: application/json):

Minimalne aplikacje interfejsu API można skonfigurować do generowania odpowiedzi na szczegóły problemu dla wszystkich odpowiedzi na błędy klienta HTTP i serwera, które nie mają jeszcze zawartości treści przy użyciu AddProblemDetails metody rozszerzenia.

Poniższy kod konfiguruje aplikację w celu wygenerowania szczegółów problemu:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();

var app = builder.Build();

app.UseExceptionHandler();
app.UseStatusCodePages();

app.MapGet("/users/{id:int}", (int id) 
    => id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)));

app.MapGet("/", () => "Test by calling /users/{id:int}");

app.Run();

public record User(int Id);

Aby uzyskać więcej informacji na temat korzystania z programu AddProblemDetails, zobacz Szczegóły problemu

Rezerwowa usługa IProblemDetailsService

W poniższym kodzie zwraca błąd, httpContext.Response.WriteAsync("Fallback: An error occurred.") jeśli IProblemDetailsService implementacja nie może wygenerować elementu ProblemDetails:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();

var app = builder.Build();

app.UseExceptionHandler(exceptionHandlerApp =>
{
    exceptionHandlerApp.Run(async httpContext =>
    {
        var pds = httpContext.RequestServices.GetService<IProblemDetailsService>();
        if (pds == null
            || !await pds.TryWriteAsync(new() { HttpContext = httpContext }))
        {
            // Fallback behavior
            await httpContext.Response.WriteAsync("Fallback: An error occurred.");
        }
    });
});

app.MapGet("/exception", () =>
{
    throw new InvalidOperationException("Sample Exception");
});

app.MapGet("/", () => "Test by calling /exception");

app.Run();

Poprzedni kod:

Poniższy przykład jest podobny do powyższego z tą różnicą, że wywołuje metodę Status Code Pages middleware.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();

var app = builder.Build();

app.UseStatusCodePages(statusCodeHandlerApp =>
{
    statusCodeHandlerApp.Run(async httpContext =>
    {
        var pds = httpContext.RequestServices.GetService<IProblemDetailsService>();
        if (pds == null
            || !await pds.TryWriteAsync(new() { HttpContext = httpContext }))
        {
            // Fallback behavior
            await httpContext.Response.WriteAsync("Fallback: An error occurred.");
        }
    });
});

app.MapGet("/users/{id:int}", (int id) =>
{
    return id <= 0 ? Results.BadRequest() : Results.Ok(new User(id));
});

app.MapGet("/", () => "Test by calling /users/{id:int}");

app.Run();

public record User(int Id);

Dodatkowe funkcje obsługi błędów

Migracja z kontrolerów do minimalnych interfejsów API

Jeśli migrujesz z interfejsów API opartych na kontrolerach do minimalnych interfejsów API:

  1. Zastępowanie filtrów akcji filtrami punktów końcowych lub oprogramowaniem pośredniczącym
  2. Zastępowanie walidacji modelu ręcznym lub powiązaniem niestandardowym
  3. Zastępowanie filtrów wyjątków oprogramowaniem pośredniczącym obsługującym wyjątki
  4. Konfigurowanie szczegółów problemu przy użyciu AddProblemDetails() funkcji spójnych odpowiedzi na błędy

Kiedy należy używać obsługi błędów opartych na kontrolerze

W razie potrzeby rozważ użycie interfejsów API opartych na kontrolerze:

  • Złożone scenariusze weryfikacji modelu
  • Scentralizowana obsługa wyjątków na wielu kontrolerach
  • Szczegółowa kontrola nad formatowaniem odpowiedzi na błędy
  • Integracja z funkcjami MVC, takimi jak filtry i konwencje

Aby uzyskać szczegółowe informacje na temat obsługi błędów opartych na kontrolerze, w tym błędów walidacji, dostosowywania szczegółów problemu i filtrów wyjątków, zobacz sekcje kart Kontrolery .

Dodatkowe zasoby