Zpracování chyb v minimálních aplikacích API
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.
Upozorňující
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v tématu .NET a .NET Core Zásady podpory. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.
Důležité
Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Aktuální verzi najdete ve verzi .NET 8 tohoto článku.
Tento článek popisuje, jak řešit chyby v minimálních aplikacích API. Informace o zpracování chyb v rozhraních API založených na kontroleru najdete v tématu Zpracování chyb v ASP.NET Core a zpracování chyb ve webových rozhraních API založených na řadiči jádra ASP.NET.
Výjimky
V aplikaci s minimálním rozhraním API existují dva různé integrované centralizované mechanismy pro zpracování neošetřených výjimek:
- Middleware stránky výjimek pro vývojáře (pouze pro použití ve vývojovém prostředí.)
- Middleware obslužné rutiny výjimek
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();
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ě:
- Běží ve vývojovém prostředí.
- Aplikace byla vytvořena s aktuálními šablonami, tj. pomocí .WebApplication.CreateBuilder
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
.
Upozorňující
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 prostředí najdete v tématu Použití více prostředí v ASP.NET Core.
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é
- Hlavičky
- 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:
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. Pří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
Zobrazení stránky výjimky pro vývojáře:
- Spusťte ukázkovou aplikaci ve vývojovém prostředí.
- Přejděte na
/exception
koncový bod.
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 Middleware
volá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ří json
200 OK
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.
Dá 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 (499
-400
) 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
):
- ExceptionHandlerMiddleware: Vygeneruje odpověď na podrobnosti o problému, pokud není definována vlastní obslužná rutina.
- StatusCodePagesMiddleware: Ve výchozím nastavení vygeneruje odpověď podrobností o problému.
- DeveloperExceptionPageMiddleware: Vygeneruje odpověď na podrobnosti o problému při vývoji, pokud hlavička
Accept
HTTP požadavku neobsahujetext/html
.
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í AddProblemDetails
naleznete 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:
- Zapíše chybovou zprávu s náhradním kódem, pokud
problemDetailsService
není schopen napsatProblemDetails
. Například koncový bod, kde hlavička přijmout požadavek určuje typ média, kterýDefaulProblemDetailsWriter
nepodporuje. - Používá middleware obslužné rutiny výjimek.
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);
Tento článek popisuje, jak řešit chyby v minimálních aplikacích API.
Výjimky
V aplikaci s minimálním rozhraním API existují dva různé integrované centralizované mechanismy pro zpracování neošetřených výjimek:
- Middleware stránky výjimek pro vývojáře (pouze pro použití ve vývojovém prostředí.)
- Middleware obslužné rutiny výjimek
Tato část se týká následující aplikace s minimálním rozhraním API, která ukazuje způsoby zpracování výjimek. Při vyžádání koncového bodu /exception
dojde k výjimce:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/exception", ()
=> { throw new InvalidOperationException("Sample Exception"); });
app.Run();
Stránka výjimky pro vývojáře
Na stránce výjimky pro vývojáře se zobrazují podrobné trasování zásobníku pro chyby serveru. 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í.
ASP.NET aplikace Core ve výchozím nastavení povolí stránku výjimky pro vývojáře, pokud jsou obě:
- Běží ve vývojovém prostředí.
- Aplikace používá WebApplication.CreateBuilder.
Další informace o konfiguraci middlewaru najdete v tématu Middleware v minimálních aplikacích API.
Při použití předchozí minimální aplikace API, když Developer Exception Page
zjistí neošetřenou výjimku, vygeneruje výchozí odpověď ve formátu prostého textu podobnou následujícímu příkladu:
HTTP/1.1 500 Internal Server Error
Content-Type: text/plain; charset=utf-8
Date: Thu, 27 Oct 2022 18:00:59 GMT
Server: Kestrel
Transfer-Encoding: chunked
System.InvalidOperationException: Sample Exception
at Program.<>c.<<Main>$>b__0_1() in ....:line 17
at lambda_method2(Closure, Object, HttpContext)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
HEADERS
=======
Accept: */*
Connection: keep-alive
Host: localhost:5239
Accept-Encoding: gzip, deflate, br
Upozorňující
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 prostředí najdete v tématu Použití více prostředí v ASP.NET Core.
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 Middleware
volá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 naleznete v části Podrobnosti o problému.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseExceptionHandler(exceptionHandlerApp
=> exceptionHandlerApp.Run(async context
=> await Results.Problem()
.ExecuteAsync(context)));
app.Map("/exception", ()
=> { throw new InvalidOperationException("Sample 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.Map("/users/{id:int}", (int id)
=> id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)) );
app.Run();
public record User(int Id);
Koncový /users
bod vytvoří json
200 OK
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.
Dá 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 (499
-400
) 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.Map("/users/{id:int}", (int id)
=> id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)) );
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
):
- ExceptionHandlerMiddleware: Vygeneruje odpověď na podrobnosti o problému, pokud není definována vlastní obslužná rutina.
- StatusCodePagesMiddleware: Ve výchozím nastavení vygeneruje odpověď podrobností o problému.
- DeveloperExceptionPageMiddleware: Vygeneruje odpověď na podrobnosti o problému při vývoji, pokud hlavička
Accept
HTTP požadavku neobsahujetext/html
.
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.Map("/users/{id:int}", (int id)
=> id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)) );
app.Map("/exception", ()
=> { throw new InvalidOperationException("Sample Exception"); });
app.Run();
Další informace o použití AddProblemDetails
naleznete v tématu Podrobnosti o problému.