Zpracování chyb ve webových rozhraních API založených na řadiči jádra ASP.NET
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
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 v tomto článku ve verzi .NET 9.
Tento článek popisuje, jak zpracovávat chyby a přizpůsobit zpracování chyb ve webových rozhraních API založených na řadiči ASP.NET Core. Informace o zpracování chyb v minimálních rozhraních API najdete v tématu Zpracování chyb v ASP.NET Core a Zpracování chyb v minimálních rozhraních API.
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:
Do rozhraní API založeného na kontroleru přidejte následující akci kontroleru. Akce vyvolá výjimku při vyžádání koncového bodu.
[HttpGet("Throw")] public IActionResult Throw() => throw new Exception("Sample exception.");
Spusťte aplikaci ve vývojovém prostředí.
Přejděte na koncový bod definovaný akcí kontroleru.
Obslužná rutina výjimky
V prostředích, která nejsou vývojová, použijte middleware zpracování výjimek k vytvoření datové části chyby:
UseExceptionHandler Voláním
Program.cs
přidejte middleware zpracování výjimek:var app = builder.Build(); app.UseHttpsRedirection(); if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/error"); } app.UseAuthorization(); app.MapControllers(); app.Run();
Nakonfigurujte akci kontroleru, která bude reagovat na trasu
/error
:[Route("/error")] public IActionResult HandleError() => Problem();
Předchozí HandleError
akce odešle klientovi datovou část kompatibilní s dokumentem RFC 7807.
Upozorňující
Neoznačí metodu akce obslužné rutiny chyby s atributy metody HTTP, například HttpGet
. Explicitní příkazy brání některým požadavkům v dosažení metody akce.
U webových rozhraní API, která používají Swagger / OpenAPI, označte akci obslužné rutiny chyby atributem [ApiExplorerSettings] a nastavte jeho IgnoreApi vlastnost na true
. Tato konfigurace atributu vylučuje akci obslužné rutiny chyby ze specifikace OpenAPI aplikace:
[ApiExplorerSettings(IgnoreApi = true)]
Povolte anonymní přístup k metodě, pokud by se měla zobrazit chyba neověřených uživatelů.
Middleware zpracování výjimek je možné použít také ve vývojovém prostředí k vytvoření konzistentního formátu datové části ve všech prostředích:
Zaregistrujte
Program.cs
instance middlewaru specifické pro prostředí:if (app.Environment.IsDevelopment()) { app.UseExceptionHandler("/error-development"); } else { app.UseExceptionHandler("/error"); }
V předchozím kódu je middleware zaregistrovaný v:
/error-development
Trasa ve vývojovém prostředí.- Trasa
/error
v prostředích, která nejsou vývojová.
Přidejte akce kontroleru pro trasy vývoje i pro jiné než vývojové trasy:
[Route("/error-development")] public IActionResult HandleErrorDevelopment( [FromServices] IHostEnvironment hostEnvironment) { if (!hostEnvironment.IsDevelopment()) { return NotFound(); } var exceptionHandlerFeature = HttpContext.Features.Get<IExceptionHandlerFeature>()!; return Problem( detail: exceptionHandlerFeature.Error.StackTrace, title: exceptionHandlerFeature.Error.Message); } [Route("/error")] public IActionResult HandleError() => Problem();
Úprava odpovědi pomocí výjimek
Obsah odpovědi lze upravit mimo kontroler pomocí vlastní výjimky a filtru akcí:
Vytvořte známý typ výjimky s názvem
HttpResponseException
:public class HttpResponseException : Exception { public HttpResponseException(int statusCode, object? value = null) => (StatusCode, Value) = (statusCode, value); public int StatusCode { get; } public object? Value { get; } }
Vytvořte filtr akcí s názvem
HttpResponseExceptionFilter
:public class HttpResponseExceptionFilter : IActionFilter, IOrderedFilter { public int Order => int.MaxValue - 10; public void OnActionExecuting(ActionExecutingContext context) { } public void OnActionExecuted(ActionExecutedContext context) { if (context.Exception is HttpResponseException httpResponseException) { context.Result = new ObjectResult(httpResponseException.Value) { StatusCode = httpResponseException.StatusCode }; context.ExceptionHandled = true; } } }
Předchozí filtr určuje
Order
maximální celočíselnou hodnotu minus 10. ToOrder
umožňuje spuštění dalších filtrů na konci kanálu.Do
Program.cs
kolekce filtrů přidejte filtr akcí:builder.Services.AddControllers(options => { options.Filters.Add<HttpResponseExceptionFilter>(); });
Odpověď na chybu ověření
U řadičů webového rozhraní API MVC odpoví typem ValidationProblemDetails odpovědi, když se ověření modelu nezdaří. MVC používá výsledky InvalidModelStateResponseFactory k vytvoření chybové odpovědi pro selhání ověření. Následující příklad nahrazuje výchozí továrnu implementací, která také podporuje formátování odpovědí jako XML, v Program.cs
:
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = context =>
new BadRequestObjectResult(context.ModelState)
{
ContentTypes =
{
// using static System.Net.Mime.MediaTypeNames;
Application.Json,
Application.Xml
}
};
})
.AddXmlSerializerFormatters();
Odpověď na chybu klienta
Výsledek chyby je definován jako výsledek se stavovým kódem HTTP 400 nebo vyšší. U řadičů webového rozhraní API MVC transformuje výsledek chyby tak, aby vytvořil ProblemDetails.
Automatické vytvoření stavových ProblemDetails
kódů chyb je ve výchozím nastavení povolené, ale odpovědi na chyby je možné nakonfigurovat jedním z následujících způsobů:
- Použití služby podrobností o problému
- Implementace ProblemDetailsFactory
- Použití apiBehaviorOptions.ClientErrorMapping
Odpověď s výchozími podrobnostmi o problému
Program.cs
Následující soubor vygenerovaly šablony webových aplikací pro kontrolery rozhraní API:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Vezměte v úvahu následující kontroler, který vrátí BadRequest , když je vstup neplatný:
[Route("api/[controller]/[action]")]
[ApiController]
public class Values2Controller : ControllerBase
{
// /api/values2/divide/1/2
[HttpGet("{Numerator}/{Denominator}")]
public IActionResult Divide(double Numerator, double Denominator)
{
if (Denominator == 0)
{
return BadRequest();
}
return Ok(Numerator / Denominator);
}
// /api/values2 /squareroot/4
[HttpGet("{radicand}")]
public IActionResult Squareroot(double radicand)
{
if (radicand < 0)
{
return BadRequest();
}
return Ok(Math.Sqrt(radicand));
}
}
Odpověď s podrobnostmi o problému se vygeneruje s předchozím kódem, pokud platí některá z následujících podmínek:
- Koncový
/api/values2/divide
bod se volá s nulovým jmenovatelem. - Koncový
/api/values2/squareroot
bod se volá s paprsky menší než nula.
Výchozí text odpovědi s podrobnostmi o problému obsahuje následující type
title
hodnoty a status
hodnoty:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Bad Request",
"status": 400,
"traceId": "00-84c1fd4063c38d9f3900d06e56542d48-85d1d4-00"
}
Služba podrobností o problému
ASP.NET Core podporuje vytváření podrobností o problému pro rozhraní HTTP API pomocí rozhraní IProblemDetailsService. Další informace najdete ve službě Podrobnosti o problému.
Následující kód nakonfiguruje aplikaci tak, aby vygenerovala odpověď na podrobnosti o problému pro všechny odpovědi na chyby klienta HTTP a serveru, které ještě nemají základní obsah:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseExceptionHandler();
app.UseStatusCodePages();
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.MapControllers();
app.Run();
Vezměte v úvahu kontroler rozhraní API z předchozí části, který se vrátí BadRequest , když je vstup neplatný:
[Route("api/[controller]/[action]")]
[ApiController]
public class Values2Controller : ControllerBase
{
// /api/values2/divide/1/2
[HttpGet("{Numerator}/{Denominator}")]
public IActionResult Divide(double Numerator, double Denominator)
{
if (Denominator == 0)
{
return BadRequest();
}
return Ok(Numerator / Denominator);
}
// /api/values2 /squareroot/4
[HttpGet("{radicand}")]
public IActionResult Squareroot(double radicand)
{
if (radicand < 0)
{
return BadRequest();
}
return Ok(Math.Sqrt(radicand));
}
}
Odpověď s podrobnostmi o problému se vygeneruje s předchozím kódem, pokud platí některá z následujících podmínek:
- Je zadán neplatný vstup.
- Identifikátor URI nemá žádný odpovídající koncový bod.
- Dojde k neošetřené výjimce.
Automatické vytvoření ProblemDetails
pro stavové kódy kódů chyb je zakázáno, pokud je vlastnost SuppressMapClientErrors nastavená na true
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressMapClientErrors = true;
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Při použití předchozího kódu se při návratu kontroleru rozhraní API vrátí BadRequest
stav odpovědi HTTP 400 bez textu odpovědi. SuppressMapClientErrors
ProblemDetails
zabraňuje vytvoření odpovědi i při volání WriteAsync
koncového bodu kontroleru rozhraní API. WriteAsync
je vysvětleno dále v tomto článku.
V další části se dozvíte, jak přizpůsobit text odpovědi s podrobnostmi o problému pomocí příkazu CustomizeProblemDetails, aby se vrátila užitečnější odpověď. Další možnosti přizpůsobení najdete v tématu Přizpůsobení podrobností o problému.
Přizpůsobení podrobností o problému pomocí CustomizeProblemDetails
Následující kód používá ProblemDetailsOptions k nastavení CustomizeProblemDetails:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddProblemDetails(options =>
options.CustomizeProblemDetails = (context) =>
{
var mathErrorFeature = context.HttpContext.Features
.Get<MathErrorFeature>();
if (mathErrorFeature is not null)
{
(string Detail, string Type) details = mathErrorFeature.MathError switch
{
MathErrorType.DivisionByZeroError =>
("Divison by zero is not defined.",
"https://wikipedia.org/wiki/Division_by_zero"),
_ => ("Negative or complex numbers are not valid input.",
"https://wikipedia.org/wiki/Square_root")
};
context.ProblemDetails.Type = details.Type;
context.ProblemDetails.Title = "Bad Input";
context.ProblemDetails.Detail = details.Detail;
}
}
);
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStatusCodePages();
app.UseAuthorization();
app.MapControllers();
app.Run();
Aktualizovaný kontroler rozhraní API:
[Route("api/[controller]/[action]")]
[ApiController]
public class ValuesController : ControllerBase
{
// /api/values/divide/1/2
[HttpGet("{Numerator}/{Denominator}")]
public IActionResult Divide(double Numerator, double Denominator)
{
if (Denominator == 0)
{
var errorType = new MathErrorFeature
{
MathError = MathErrorType.DivisionByZeroError
};
HttpContext.Features.Set(errorType);
return BadRequest();
}
return Ok(Numerator / Denominator);
}
// /api/values/squareroot/4
[HttpGet("{radicand}")]
public IActionResult Squareroot(double radicand)
{
if (radicand < 0)
{
var errorType = new MathErrorFeature
{
MathError = MathErrorType.NegativeRadicandError
};
HttpContext.Features.Set(errorType);
return BadRequest();
}
return Ok(Math.Sqrt(radicand));
}
}
Následující kód obsahuje MathErrorFeature
kód, MathErrorType
který se používá s předchozím vzorem:
// Custom Http Request Feature
class MathErrorFeature
{
public MathErrorType MathError { get; set; }
}
// Custom math errors
enum MathErrorType
{
DivisionByZeroError,
NegativeRadicandError
}
Odpověď s podrobnostmi o problému se vygeneruje s předchozím kódem, pokud platí některá z následujících podmínek:
- Koncový
/divide
bod se volá s nulovým jmenovatelem. - Koncový
/squareroot
bod se volá s paprsky menší než nula. - Identifikátor URI nemá žádný odpovídající koncový bod.
Text odpovědi s podrobnostmi o problému obsahuje následující informace, pokud je volán některý squareroot
koncový bod s radikandou menší než nula:
{
"type": "https://en.wikipedia.org/wiki/Square_root",
"title": "Bad Input",
"status": 400,
"detail": "Negative or complex numbers are not allowed."
}
Zobrazení nebo stažení ukázkového kódu
Implementovat ProblemDetailsFactory
MVC používá Microsoft.AspNetCore.Mvc.Infrastructure.ProblemDetailsFactory k vytvoření všech instancí ProblemDetails a ValidationProblemDetails. Tato továrna se používá pro:
- Odpovědi na chyby klienta
- Odpovědi na chyby selhání ověřování
- ControllerBase.Problem a ControllerBase.ValidationProblem
Pokud chcete přizpůsobit odpověď na podrobnosti problému, zaregistrujte vlastní implementaci ProblemDetailsFactory v Program.cs
:
builder.Services.AddControllers();
builder.Services.AddTransient<ProblemDetailsFactory, SampleProblemDetailsFactory>();
Použití ApiBehaviorOptions.ClientErrorMapping
ClientErrorMapping Pomocí vlastnosti můžete nakonfigurovat obsah ProblemDetails
odpovědi. Například následující kód v Program.cs
aktualizaci Link vlastnosti pro odpovědi 404:
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
});
Další materiály
Tento článek popisuje, jak zpracovávat chyby a přizpůsobit zpracování chyb pomocí webových rozhraní API ASP.NET Core.
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í. Představte si například následující akci kontroleru, která vyvolá výjimku:
[HttpGet("Throw")]
public IActionResult Throw() =>
throw new Exception("Sample exception.");
Když stránka výjimky vývojáře 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
Server: Kestrel
Transfer-Encoding: chunked
System.Exception: Sample exception.
at HandleErrorsSample.Controllers.ErrorsController.Get() in ...
at lambda_method1(Closure , Object , Object[] )
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
...
Pokud klient požádá o odpověď ve formátu HTML, stránka výjimky vývojáře vygeneruje odpověď podobnou následujícímu příkladu:
HTTP/1.1 500 Internal Server Error
Content-Type: text/html; charset=utf-8
Server: Kestrel
Transfer-Encoding: chunked
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Internal Server Error</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Arial, Helvetica, sans-serif;
font-size: .813em;
color: #222;
background-color: #fff;
}
h1 {
color: #44525e;
margin: 15px 0 15px 0;
}
...
Pokud chcete požádat o odpověď ve formátu HTML, nastavte hlavičku Accept
požadavku HTTP na text/html
.
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 zpracování výjimek k vytvoření datové části chyby:
UseExceptionHandler Voláním
Program.cs
přidejte middleware zpracování výjimek:var app = builder.Build(); app.UseHttpsRedirection(); if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/error"); } app.UseAuthorization(); app.MapControllers(); app.Run();
Nakonfigurujte akci kontroleru, která bude reagovat na trasu
/error
:[Route("/error")] public IActionResult HandleError() => Problem();
Předchozí HandleError
akce odešle klientovi datovou část kompatibilní s dokumentem RFC 7807.
Upozorňující
Neoznačí metodu akce obslužné rutiny chyby s atributy metody HTTP, například HttpGet
. Explicitní příkazy brání některým požadavkům v dosažení metody akce.
U webových rozhraní API, která používají Swagger / OpenAPI, označte akci obslužné rutiny chyby atributem [ApiExplorerSettings] a nastavte jeho IgnoreApi vlastnost na true
. Tato konfigurace atributu vylučuje akci obslužné rutiny chyby ze specifikace OpenAPI aplikace:
[ApiExplorerSettings(IgnoreApi = true)]
Povolte anonymní přístup k metodě, pokud by se měla zobrazit chyba neověřených uživatelů.
Middleware zpracování výjimek je možné použít také ve vývojovém prostředí k vytvoření konzistentního formátu datové části ve všech prostředích:
Zaregistrujte
Program.cs
instance middlewaru specifické pro prostředí:if (app.Environment.IsDevelopment()) { app.UseExceptionHandler("/error-development"); } else { app.UseExceptionHandler("/error"); }
V předchozím kódu je middleware zaregistrovaný v:
/error-development
Trasa ve vývojovém prostředí.- Trasa
/error
v prostředích, která nejsou vývojová.
Přidejte akce kontroleru pro trasy vývoje i pro jiné než vývojové trasy:
[Route("/error-development")] public IActionResult HandleErrorDevelopment( [FromServices] IHostEnvironment hostEnvironment) { if (!hostEnvironment.IsDevelopment()) { return NotFound(); } var exceptionHandlerFeature = HttpContext.Features.Get<IExceptionHandlerFeature>()!; return Problem( detail: exceptionHandlerFeature.Error.StackTrace, title: exceptionHandlerFeature.Error.Message); } [Route("/error")] public IActionResult HandleError() => Problem();
Úprava odpovědi pomocí výjimek
Obsah odpovědi lze upravit mimo kontroler pomocí vlastní výjimky a filtru akcí:
Vytvořte známý typ výjimky s názvem
HttpResponseException
:public class HttpResponseException : Exception { public HttpResponseException(int statusCode, object? value = null) => (StatusCode, Value) = (statusCode, value); public int StatusCode { get; } public object? Value { get; } }
Vytvořte filtr akcí s názvem
HttpResponseExceptionFilter
:public class HttpResponseExceptionFilter : IActionFilter, IOrderedFilter { public int Order => int.MaxValue - 10; public void OnActionExecuting(ActionExecutingContext context) { } public void OnActionExecuted(ActionExecutedContext context) { if (context.Exception is HttpResponseException httpResponseException) { context.Result = new ObjectResult(httpResponseException.Value) { StatusCode = httpResponseException.StatusCode }; context.ExceptionHandled = true; } } }
Předchozí filtr určuje
Order
maximální celočíselnou hodnotu minus 10. ToOrder
umožňuje spuštění dalších filtrů na konci kanálu.Do
Program.cs
kolekce filtrů přidejte filtr akcí:builder.Services.AddControllers(options => { options.Filters.Add<HttpResponseExceptionFilter>(); });
Odpověď na chybu ověření
U řadičů webového rozhraní API MVC odpoví typem ValidationProblemDetails odpovědi, když se ověření modelu nezdaří. MVC používá výsledky InvalidModelStateResponseFactory k vytvoření chybové odpovědi pro selhání ověření. Následující příklad nahrazuje výchozí továrnu implementací, která také podporuje formátování odpovědí jako XML, v Program.cs
:
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = context =>
new BadRequestObjectResult(context.ModelState)
{
ContentTypes =
{
// using static System.Net.Mime.MediaTypeNames;
Application.Json,
Application.Xml
}
};
})
.AddXmlSerializerFormatters();
Odpověď na chybu klienta
Výsledek chyby je definován jako výsledek se stavovým kódem HTTP 400 nebo vyšší. U řadičů webového rozhraní API MVC transformuje výsledek chyby tak, aby vytvořil ProblemDetails.
Odpověď na chybu je možné nakonfigurovat jedním z následujících způsobů:
Implementovat ProblemDetailsFactory
MVC používá Microsoft.AspNetCore.Mvc.Infrastructure.ProblemDetailsFactory k vytvoření všech instancí ProblemDetails a ValidationProblemDetails. Tato továrna se používá pro:
- Odpovědi na chyby klienta
- Odpovědi na chyby selhání ověřování
- ControllerBase.Problem a ControllerBase.ValidationProblem
Pokud chcete přizpůsobit odpověď na podrobnosti problému, zaregistrujte vlastní implementaci ProblemDetailsFactory v Program.cs
:
builder.Services.AddControllers();
builder.Services.AddTransient<ProblemDetailsFactory, SampleProblemDetailsFactory>();
Použití ApiBehaviorOptions.ClientErrorMapping
ClientErrorMapping Pomocí vlastnosti můžete nakonfigurovat obsah ProblemDetails
odpovědi. Například následující kód v Program.cs
aktualizaci Link vlastnosti pro odpovědi 404:
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
});
Vlastní middleware pro zpracování výjimek
Výchozí hodnoty v middlewaru pro zpracování výjimek fungují pro většinu aplikací dobře. U aplikací, které vyžadují specializované zpracování výjimek, zvažte přizpůsobení middlewaru zpracování výjimek.
Vytvoření datové části ProblemDetails pro výjimky
ASP.NET Core nevytváří standardizovanou datovou část chyby, když dojde k neošetřené výjimce. Ve scénářích, ve kterých je žádoucí vrátit standardizovanou odezvu ProblemDetails klientovi, lze middleware ProblemDetails použít k mapování výjimek a 404 odpovědí na datovou část ProblemDetails . Middleware pro zpracování výjimek se dá použít také k vrácení ProblemDetails datové části pro neošetřené výjimky.
Další materiály
Tento článek popisuje, jak zpracovávat a přizpůsobovat zpracování chyb pomocí webových rozhraní API ASP.NET Core.
Zobrazení nebo stažení ukázkového kódu (stažení)
Stránka výjimky pro vývojáře
Stránka výjimky pro vývojáře je užitečný nástroj pro získání podrobných 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í. Pro ilustraci zvažte následující akci kontroleru:
[HttpGet("{city}")]
public WeatherForecast Get(string city)
{
if (!string.Equals(city?.TrimEnd(), "Redmond", StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException(
$"We don't offer a weather forecast for {city}.", nameof(city));
}
return GetWeather().First();
}
Spuštěním následujícího curl
příkazu otestujte předchozí akci:
curl -i https://localhost:5001/weatherforecast/chicago
Na stránce výjimky vývojáře se zobrazí odpověď ve formátu prostého textu, pokud klient nepožádá o výstup ve formátu HTML. Objeví se následující výstup:
HTTP/1.1 500 Internal Server Error
Transfer-Encoding: chunked
Content-Type: text/plain
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Fri, 27 Sep 2019 16:13:16 GMT
System.ArgumentException: We don't offer a weather forecast for chicago. (Parameter 'city')
at WebApiSample.Controllers.WeatherForecastController.Get(String city) in C:\working_folder\aspnet\AspNetCore.Docs\aspnetcore\web-api\handle-errors\samples\3.x\Controllers\WeatherForecastController.cs:line 34
at lambda_method(Closure , Object , Object[] )
at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
HEADERS
=======
Accept: */*
Host: localhost:44312
User-Agent: curl/7.55.1
Pokud chcete místo toho zobrazit odpověď ve formátu HTML, nastavte hlavičku Accept
požadavku HTTP na text/html
typ média. Příklad:
curl -i -H "Accept: text/html" https://localhost:5001/weatherforecast/chicago
Podívejte se na následující výňatek z odpovědi HTTP:
HTTP/1.1 500 Internal Server Error
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Fri, 27 Sep 2019 16:55:37 GMT
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Internal Server Error</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Arial, Helvetica, sans-serif;
font-size: .813em;
color: #222;
background-color: #fff;
}
Odpověď ve formátu HTML se stane užitečnou při testování pomocí nástrojů, jako je curl.
Upozorňující
Povolte stránku výjimky vývojáře jenom v případech, kdy je aplikace 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.
Neoznačí metodu akce obslužné rutiny chyby s atributy metody HTTP, například HttpGet
. Explicitní příkazy brání některým požadavkům v dosažení metody akce. Povolte anonymní přístup k metodě, pokud by se měla zobrazit chyba neověřených uživatelů.
Obslužná rutina výjimky
V prostředích, která nejsou vývojová, se dá middleware zpracování výjimek použít k vytvoření datové části chyby:
V
Startup.Configure
příkazu vyvolání UseExceptionHandler pro použití middlewaru:public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/error"); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
Nakonfigurujte akci kontroleru, která bude reagovat na trasu
/error
:[ApiController] public class ErrorController : ControllerBase { [Route("/error")] public IActionResult Error() => Problem(); }
Předchozí Error
akce odešle klientovi datovou část kompatibilní s dokumentem RFC 7807.
Middleware zpracování výjimek může také poskytovat podrobnější výstup vyjednaný obsah v místním vývojovém prostředí. Pomocí následujících kroků vytvořte konzistentní formát datové části napříč vývojovými a produkčními prostředími:
Zaregistrujte
Startup.Configure
instance middlewaru specifické pro prostředí:public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseExceptionHandler("/error-local-development"); } else { app.UseExceptionHandler("/error"); } }
V předchozím kódu je middleware zaregistrovaný v:
/error-local-development
Trasa ve vývojovém prostředí.- Trasa
/error
v prostředích, která nejsou vývojová.
Použití směrování atributů na akce kontroleru:
[ApiController] public class ErrorController : ControllerBase { [Route("/error-local-development")] public IActionResult ErrorLocalDevelopment( [FromServices] IWebHostEnvironment webHostEnvironment) { if (webHostEnvironment.EnvironmentName != "Development") { throw new InvalidOperationException( "This shouldn't be invoked in non-development environments."); } var context = HttpContext.Features.Get<IExceptionHandlerFeature>(); return Problem( detail: context.Error.StackTrace, title: context.Error.Message); } [Route("/error")] public IActionResult Error() => Problem(); }
Předchozí kód volá ControllerBase.Problem k vytvoření ProblemDetails odpovědi.
Úprava odpovědi pomocí výjimek
Obsah odpovědi lze upravit mimo kontroler. V ASP.NET webovém rozhraní API 4.x to bylo jedním ze způsobů, jak to udělat, byl HttpResponseException typ. ASP.NET Core neobsahuje ekvivalentní typ. Podporu můžete HttpResponseException
přidat pomocí následujících kroků:
Vytvořte známý typ výjimky s názvem
HttpResponseException
:public class HttpResponseException : Exception { public int Status { get; set; } = 500; public object Value { get; set; } }
Vytvořte filtr akcí s názvem
HttpResponseExceptionFilter
:public class HttpResponseExceptionFilter : IActionFilter, IOrderedFilter { public int Order { get; } = int.MaxValue - 10; public void OnActionExecuting(ActionExecutingContext context) { } public void OnActionExecuted(ActionExecutedContext context) { if (context.Exception is HttpResponseException exception) { context.Result = new ObjectResult(exception.Value) { StatusCode = exception.Status, }; context.ExceptionHandled = true; } } }
Předchozí filtr určuje
Order
maximální celočíselnou hodnotu minus 10. ToOrder
umožňuje spuštění dalších filtrů na konci kanálu.Do
Startup.ConfigureServices
kolekce filtrů přidejte filtr akcí:services.AddControllers(options => options.Filters.Add(new HttpResponseExceptionFilter()));
Odpověď na chybu ověření
U řadičů webového rozhraní API MVC odpoví typem ValidationProblemDetails odpovědi, když se ověření modelu nezdaří. MVC používá výsledky InvalidModelStateResponseFactory k vytvoření chybové odpovědi pro selhání ověření. Následující příklad používá továrnu ke změně výchozího typu odpovědi na SerializableError hodnotu in Startup.ConfigureServices
:
services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = context =>
{
var result = new BadRequestObjectResult(context.ModelState);
// TODO: add `using System.Net.Mime;` to resolve MediaTypeNames
result.ContentTypes.Add(MediaTypeNames.Application.Json);
result.ContentTypes.Add(MediaTypeNames.Application.Xml);
return result;
};
});
Odpověď na chybu klienta
Výsledek chyby je definován jako výsledek se stavovým kódem HTTP 400 nebo vyšší. U řadičů webového rozhraní API MVC transformuje výsledek chyby na výsledek pomocí ProblemDetails.
Odpověď na chybu je možné nakonfigurovat jedním z následujících způsobů:
Implementovat ProblemDetailsFactory
MVC používá Microsoft.AspNetCore.Mvc.Infrastructure.ProblemDetailsFactory k vytvoření všech instancí ProblemDetails a ValidationProblemDetails. Tato továrna se používá pro:
- Odpovědi na chyby klienta
- Odpovědi na chyby selhání ověřování
- ControllerBase.Problem a ControllerBase.ValidationProblem
Pokud chcete přizpůsobit odpověď na podrobnosti problému, zaregistrujte vlastní implementaci ProblemDetailsFactory v Startup.ConfigureServices
:
public void ConfigureServices(IServiceCollection serviceCollection)
{
services.AddControllers();
services.AddTransient<ProblemDetailsFactory, CustomProblemDetailsFactory>();
}
Použití apiBehaviorOptions.ClientErrorMapping
ClientErrorMapping Pomocí vlastnosti můžete nakonfigurovat obsah ProblemDetails
odpovědi. Například následující kód v Startup.ConfigureServices
aktualizaci type
vlastnosti pro odpovědi 404:
services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
options.DisableImplicitFromServicesParameters = true;
});
Vlastní middleware pro zpracování výjimek
Výchozí hodnoty v middlewaru pro zpracování výjimek fungují pro většinu aplikací dobře. U aplikací, které vyžadují specializované zpracování výjimek, zvažte přizpůsobení middlewaru zpracování výjimek.
Vytvoření datové části ProblemDetails pro výjimky
ASP.NET Core nevytváří standardizovanou datovou část chyby, když dojde k neošetřené výjimce. Ve scénářích, ve kterých je žádoucí vrátit standardizovanou odezvu ProblemDetails klientovi, lze middleware ProblemDetails použít k mapování výjimek a 404 odpovědí na datovou část ProblemDetails . Middleware pro zpracování výjimek se dá použít také k vrácení ProblemDetails datové části pro neošetřené výjimky.