Sdílet prostřednictvím


Zpracování chyb v rozhraních API ASP.NET Core

Poznámka:

Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 10 tohoto článku.

Výstraha

Tato verze ASP.NET Core již není podporována. Pro více informací se podívejte na Zásady podpory .NET a .NET Core. Aktuální vydání tohoto článku najdete v verzi .NET 9.

Tento článek popisuje, jak zpracovávat chyby v rozhraních ASP.NET Core API. Je vybraná dokumentace k minimálním rozhraním API. Pokud chcete zobrazit dokumentaci pro rozhraní API založená na kontroleru, vyberte kartu Kontrolery. Pokyny pro Blazor zpracování chyb najdete v tématu Zpracování chyb v aplikacích ASP.NET CoreBlazor.

Stránka výjimky pro vývojáře

Na stránce výjimka pro vývojáře se zobrazují podrobné informace o neošetřených výjimkách požadavků. Používá DeveloperExceptionPageMiddleware se k zaznamenání synchronních a asynchronních výjimek z kanálu HTTP a k vygenerování chybových odpovědí. Stránka výjimky vývojáře se spouští v rané fázi kanálu middlewaru, aby bylo možné zachytit neošetřené výjimky vyvolané v middlewaru, které následuje.

ASP.NET aplikace Core ve výchozím nastavení povolí stránku výjimky pro vývojáře, pokud jsou obě:

Aplikace vytvořené pomocí dřívějších šablon, tj. pomocí WebHost.CreateDefaultBuilder, mohou povolit stránku výjimky vývojáře voláním app.UseDeveloperExceptionPage.

Výstraha

Nepovolujte stránku výjimek vývojáře , pokud aplikace není spuštěná ve vývojovém prostředí. Nesdílejte podrobné informace o výjimce veřejně, když aplikace běží v produkčním prostředí. Další informace o konfiguraci runtime prostředí najdete v tématu prostředí ASP.NET Core runtime.

Stránka výjimky pro vývojáře může obsahovat následující informace o výjimce a požadavku:

  • Trasování zásobníku
  • Parametry řetězce dotazu, pokud nějaké
  • Soubory cookie, pokud nějaké
  • Headers
  • Metadata koncového bodu, pokud existuje

Na stránce výjimky pro vývojáře není zaručeno, že poskytnete žádné informace. Protokolování slouží k úplným informacím o chybě.

Následující obrázek ukazuje ukázkovou stránku výjimky vývojáře s animací, která zobrazuje karty a zobrazené informace:

Stránka výjimky vývojáře animované pro zobrazení jednotlivých vybraných karet

V reakci na požadavek s hlavičkou Accept: text/plain vrátí stránka výjimky vývojáře místo HTML prostý text. Například:

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

Pokud chcete zobrazit stránku výjimky vývojáře v minimálním rozhraní API:

Tato část odkazuje na následující ukázkovou aplikaci, která demonstruje způsoby zpracování výjimek v minimálním rozhraní API. Při vyžádání koncového bodu /exception dojde k výjimce:

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();

Obslužná rutina výjimky

V prostředích, která nejsou vývojová, použijte middleware obslužné rutiny výjimky k vytvoření datové části chyby.

Konfigurace Exception Handler Middlewarevolání UseExceptionHandler. Následující kód například změní aplikaci tak, aby odpovídala datové části kompatibilní s dokumentem RFC 7807 pro klienta. Další informace najdete v části Podrobnosti o problému dále v tomto článku.

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();

Odpovědi na chyby klienta a serveru

Zvažte následující minimální aplikaci 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);

Koncový /users bod vytvoří 200 OKjson reprezentaciUser, kdy id je větší než 0, jinak stavový 400 BAD REQUEST kód bez textu odpovědi. Další informace o vytvoření odpovědi najdete v tématu Vytváření odpovědí v minimálních aplikacích API.

Status Code Pages middleware se nakonfigurovat tak, aby vytvářel společný základní obsah, pokud je prázdný, pro všechny odpovědi klienta HTTP (400-499) nebo serveru ().500 -599 Middleware je nakonfigurován voláním UseStatusCodePages rozšiřující metoda.

Následující příklad například změní aplikaci tak, aby reagovala na datovou část kompatibilní se standardem RFC 7807 pro klienta pro všechny odpovědi klienta a serveru, včetně chyb směrování (například 404 NOT FOUND). Další informace najdete v části Podrobnosti o problému .

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);

Podrobnosti o problému

Podrobnosti o problému nejsou jediným formátem odpovědi, který popisuje chybu rozhraní HTTP API, ale běžně se používají k hlášení chyb pro rozhraní HTTP API.

Služba podrobností problému implementuje IProblemDetailsService rozhraní, které podporuje vytváření podrobností o problému v ASP.NET Core. Metoda AddProblemDetails(IServiceCollection) rozšíření při IServiceCollection registraci výchozí IProblemDetailsService implementace.

V aplikacích ASP.NET Core generuje následující middleware při zavolání podrobnosti o problému odpovědi AddProblemDetails HTTP, s výjimkou případů, kdy Accept hlavička HTTP požadavku neobsahuje jeden z typů obsahu podporovaných zaregistrovaným IProblemDetailsWriter (výchozí): application/json

Minimální aplikace API je možné nakonfigurovat tak, aby generovaly odpověď na podrobnosti o problému pro všechny odpovědi na chyby klienta HTTP a serveru, které ještě nemají základní obsah pomocí AddProblemDetails metody rozšíření.

Následující kód nakonfiguruje aplikaci tak, aby vygenerovala podrobnosti o problému:

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);

Další informace o použití AddProblemDetailsnaleznete v tématu Podrobnosti o problému.

Náhradní služba IProblemDetailsService

V následujícím kódu vrátí chybu, httpContext.Response.WriteAsync("Fallback: An error occurred.") pokud IProblemDetailsService implementace nemůže vygenerovat 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();

Předchozí kód:

Následující ukázka je podobná předchozímu s tím rozdílem, že volá 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);

Další funkce zpracování chyb

Migrace z kontrolerů na minimální rozhraní API

Pokud migrujete z rozhraní API založených na kontroleru na minimální rozhraní API:

  1. Nahrazení filtrů akcí filtry koncových bodů nebo middlewaru
  2. Nahrazení ověření modelu ručním ověřením nebo vlastní vazbou
  3. Nahrazení filtrů výjimek middlewarem zpracování výjimek
  4. Konfigurace podrobností o problémech s využitím AddProblemDetails() konzistentních odpovědí na chyby

Kdy použít zpracování chyb na základě kontroleru

Pokud potřebujete, zvažte rozhraní API založená na kontroleru:

  • Scénáře komplexního ověřování modelu
  • Centralizované zpracování výjimek napříč několika kontrolery
  • Jemně odstupňovaná kontrola nad formátováním odpovědí na chyby
  • Integrace s funkcemi MVC, jako jsou filtry a konvence

Podrobné informace o zpracování chyb na základě kontroleru, včetně chyb ověření, přizpůsobení podrobností o problému a filtrů výjimek, najdete v částech karty Kontrolery .

Dodatečné zdroje