Fouten in ASP.NET Core API's verwerken

Opmerking

Dit is niet de nieuwste versie van dit artikel. Zie de .NET 10-versie van dit artikel voor de huidige release.

Waarschuwing

Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie het .NET en .NET Core Support Policy voor meer informatie. Zie de .NET 10-versie van dit artikel voor de huidige release.

In dit artikel wordt beschreven hoe u fouten in ASP.NET Core API's kunt verwerken. Documentatie voor minimale API's is geselecteerd. Selecteer het tabblad Controllers voor documentatie voor api's op basis van een controller. Zie Blazor voor Blazor foutafhandelingsrichtlijnen.

Uitzonderingspagina voor ontwikkelaars

Op de uitzonderingspagina voor ontwikkelaars wordt gedetailleerde informatie weergegeven over niet-verwerkte aanvraag-uitzonderingen. Het maakt gebruik DeveloperExceptionPageMiddleware van het vastleggen van synchrone en asynchrone uitzonderingen van de HTTP-pijplijn en voor het genereren van foutreacties. De foutpagina voor ontwikkelaars draait vroeg in de middleware-pijplijn, zodat niet-verwerkte uitzonderingen kunnen worden opgevangen die optreden in de daaropvolgende middleware.

ASP.NET Core apps de uitzonderingspagina voor ontwikkelaars standaard inschakelen wanneer beide:

Apps die zijn gemaakt met behulp van eerdere sjablonen, dat wil zeggen door WebHost.CreateDefaultBuilder te gebruiken, kunnen de uitzonderingspagina voor ontwikkelaars inschakelen door app.UseDeveloperExceptionPage aan te roepen.

Waarschuwing

Schakel de uitzonderingspagina voor ontwikkelaars alleen in als de app wordt uitgevoerd in de Development omgeving. Deel geen gedetailleerde uitzonderingsgegevens openbaar wanneer de app in productie wordt uitgevoerd. Zie ASP.NET Core runtime-omgevingen voor meer informatie over het configureren van omgevingen.

De uitzonderingspagina voor ontwikkelaars kan de volgende informatie bevatten over de uitzondering en de aanvraag:

  • Stacktracering
  • Queryreeksparameters, indien van toepassing
  • Cookies, indien van toepassing
  • Headers
  • Eindpuntmetagegevens, indien van toepassing

De uitzonderingspagina voor ontwikkelaars is niet gegarandeerd informatie te verstrekken. Gebruik Logging voor volledige foutinformatie.

In de volgende afbeelding ziet u een voorbeeld van een uitzonderingspagina voor ontwikkelaars met animatie om de tabbladen en de weergegeven informatie weer te geven:

Ontwikkelaar uitzondering pagina geanimeerd om te laten zien welk tabblad is geselecteerd.

Als reactie op een aanvraag met een Accept: text/plain header retourneert de uitzonderingspagina voor ontwikkelaars tekst zonder opmaak in plaats van HTML. Voorbeeld:

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

De uitzonderingspagina voor ontwikkelaars in een minimale API bekijken:

Deze sectie verwijst naar de volgende voorbeeld-app om manieren te demonstreren voor het afhandelen van uitzonderingen in een minimale API. Er wordt een uitzondering gegenereerd wanneer het eindpunt /exception wordt aangevraagd:

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

Uitzonderingshandler

Gebruik in niet-ontwikkelomgevingen de middleware voor uitzonderingsafhandeling om een foutpayload te genereren.

Om de exception handler middleware te configureren, roept u UseExceptionHandler aan. De volgende code zorgt er bijvoorbeeld voor dat de app reageert met een RFC 7807-compatibele payload aan de client. Zie de sectie Probleemdetails verderop in dit artikel voor meer informatie.

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

Antwoorden op client- en serverfouten

Houd rekening met de volgende minimale API-app.

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

Het /users eindpunt produceert 200 OK met een json weergave van User wanneer id deze groter is dan 0, anders een 400 BAD REQUEST statuscode zonder antwoordtekst. Zie Antwoorden maken in minimale API-apps voor meer informatie over het maken van een antwoord.

De Status Code Pages middleware kan worden geconfigureerd om een algemene hoofdtekstinhoud te produceren, wanneer deze leeg is, voor alle HTTP-clientreacties (400-499) of serverreacties.500 -599 De middleware wordt geconfigureerd door de useStatusCodePages-extensiemethode aan te roepen.

In het volgende voorbeeld wordt de app bijvoorbeeld gewijzigd zodat deze voor alle client- en serverreacties, inclusief routeringsfouten (bijvoorbeeld ), met een 404 NOT FOUND aan de client reageert. Zie de sectie Probleemdetails voor meer informatie.

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

Details van probleem

Probleemdetails zijn niet de enige antwoordindeling voor het beschrijven van een HTTP-API-fout. Ze worden echter vaak gebruikt om fouten voor HTTP-API's te rapporteren.

De service voor probleemdetails implementeert de interface IProblemDetailsService, die ondersteuning biedt voor het maken van probleemdetails in ASP.NET Core. De AddProblemDetails(IServiceCollection)-extensiemethode op IServiceCollection registreert de standaard IProblemDetailsService-implementatie.

In ASP.NET Core-apps genereert de volgende middleware HTTP-probleemdetaillantwoorden wanneer AddProblemDetails wordt aangeroepen, behalve wanneer de HTTP-header van het Accept verzoek geen van de inhoudstypen bevat die worden ondersteund door de geregistreerde IProblemDetailsWriter (standaard: application/json):

Minimale API-apps kunnen worden geconfigureerd om antwoord op probleemdetails te genereren voor alle HTTP-client- en serverfoutreacties die nog geen hoofdtekstinhoud hebben met behulp van de AddProblemDetails extensiemethode.

Met de volgende code wordt de app geconfigureerd voor het genereren van probleemdetails:

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

Zie AddProblemDetails voor meer informatie over het gebruik van

Fallback IProblemDetailsService

In de volgende code retourneert httpContext.Response.WriteAsync("Fallback: An error occurred.") een fout als de implementatie van IProblemDetailsService niet in staat is een ProblemDetails te genereren:

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

De voorgaande code:

Opmerking

DefaultProblemDetailsWriter ondersteunt de volgende mediatypen in de Accept requestheader:

  • application/json
  • application/problem+json
  • Wildcardtypen zoals */* en application/*

Niet-JSON-mediatypen, zoals application/xml of text/html, worden niet ondersteund en activeren het terugvalgedrag.

Het volgende voorbeeld is vergelijkbaar met het voorgaande, behalve dat het de Status Code Pages middleware aanroept.

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

Aanvullende functies voor foutafhandeling

Migratie van controllers naar minimale API's

Als u migreert van api's op basis van een controller naar minimale API's:

  1. Actiefilters vervangen door eindpuntfilters of middleware
  2. Modelvalidatie vervangen door handmatige validatie of aangepaste binding
  3. Uitzonderingsfilters vervangen door middleware voor uitzonderingsafhandeling
  4. Probleemdetails configureren met AddProblemDetails() voor consistente foutreacties

Wanneer gebruikt men controller-gebaseerde foutafhandeling?

Overweeg api's op basis van een controller als u het volgende nodig hebt:

  • Complexe modelvalidatiescenario's
  • Gecentraliseerde verwerking van uitzonderingen op meerdere controllers
  • Fijnmazige controle over de opmaak van foutmeldingen
  • Integratie met MVC-functies zoals filters en conventies

Zie de tabbladsecties Controllers voor gedetailleerde informatie over foutafhandeling op basis van controller, waaronder validatiefouten, aanpassing van probleemdetails en uitzonderingsfilters .

Aanvullende bronnen