-
Notifications
You must be signed in to change notification settings - Fork 24.8k
Problem details /2 #27009
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Problem details /2 #27009
Changes from all commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
57155d6
moniker prep
Rick-Anderson f082a15
Problem details service /2
Rick-Anderson a17a7d0
Merge branch 'main' into nMonPrep
Rick-Anderson 32196f9
Problem details service /2
Rick-Anderson 23e2041
work
Rick-Anderson 092e444
work
Rick-Anderson 9bc9ba0
Update docker-compose-https.md
Rick-Anderson 7178277
work
Rick-Anderson 954bc2f
Merge branch 'nMonPrep' of https://github.com/dotnet/AspNetCore.Docs …
Rick-Anderson c251998
work
Rick-Anderson 8465f6d
work
Rick-Anderson 102a9c9
work
Rick-Anderson 9b91236
work
Rick-Anderson e143b0c
work
Rick-Anderson 4d46420
work
Rick-Anderson 8294896
work
Rick-Anderson 456bcd7
work
Rick-Anderson adab4de
work
Rick-Anderson 9e14ac2
work
Rick-Anderson db02f54
work
Rick-Anderson 275beaa
work
Rick-Anderson 05780d3
work
Rick-Anderson cfd0f8a
work
Rick-Anderson e2d0b67
work
Rick-Anderson 3850735
Apply suggestions from code review
Rick-Anderson d293e41
react to feedback
Rick-Anderson d439c24
react to feedback
Rick-Anderson 1a5d61c
react to feedback
Rick-Anderson f6ea501
react to feedback
Rick-Anderson 70e65ff
Update aspnetcore/web-api/handle-errors.md
Rick-Anderson 4acc412
react to feedback
Rick-Anderson eb561a5
react to feedback
Rick-Anderson 02db364
Apply suggestions from code review
Rick-Anderson 584825c
react to feedback
Rick-Anderson 1120a9f
react to feedback
Rick-Anderson e3163b0
react to feedback
Rick-Anderson 05e1fa2
react to feedback
Rick-Anderson 302ba16
react to feedback
Rick-Anderson b11dc6d
react to feedback
Rick-Anderson ac27e7f
react to feedback
Rick-Anderson File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,7 +5,7 @@ description: Learn about error handling with ASP.NET Core web APIs. | |
| monikerRange: '>= aspnetcore-3.1' | ||
| ms.author: riande | ||
| ms.custom: mvc | ||
| ms.date: 9/09/2022 | ||
| ms.date: 9/23/2022 | ||
| uid: web-api/handle-errors | ||
| --- | ||
| # Handle errors in ASP.NET Core web APIs | ||
|
|
@@ -14,6 +14,8 @@ uid: web-api/handle-errors | |
|
|
||
| This article describes how to handle errors and customize error handling with ASP.NET Core web APIs. | ||
|
|
||
| <a name="dep7"></a> | ||
|
|
||
| ## Developer Exception Page | ||
|
|
||
| The [Developer Exception Page](xref:fundamentals/error-handling) shows detailed stack traces for server errors. It uses <xref:Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware> to capture synchronous and asynchronous exceptions from the HTTP pipeline and to generate error responses. For example, consider the following controller action, which throws an exception: | ||
|
|
@@ -140,13 +142,156 @@ For web API controllers, MVC responds with a <xref:Microsoft.AspNetCore.Mvc.Vali | |
|
|
||
| ## Client error response | ||
|
|
||
| An *error result* is defined as a result with an HTTP status code of 400 or higher. For web API controllers, MVC transforms an error result to a produce a <xref:Microsoft.AspNetCore.Mvc.ProblemDetails>. | ||
| An *error result* is defined as a result with an HTTP status code of 400 or higher. For web API controllers, MVC transforms an error result to produce a <xref:Microsoft.AspNetCore.Mvc.ProblemDetails>. | ||
|
|
||
| The error response can be configured in one of the following ways: | ||
| The automatic creation of a `ProblemDetails` for error status codes is enabled by default, but error responses can be configured in one of the following ways: | ||
|
|
||
| 1. Use the [problem details service](#pds7) | ||
| 1. [Implement ProblemDetailsFactory](#implement-problemdetailsfactory) | ||
| 1. [Use ApiBehaviorOptions.ClientErrorMapping](#use-apibehavioroptionsclienterrormapping) | ||
|
|
||
| ### Default problem details response | ||
|
|
||
| The following `Program.cs` file was generated by the web application templates for API controllers: | ||
|
|
||
| :::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Program.cs" id="snippet_default"::: | ||
|
|
||
| Consider the following controller, which returns <xref:Microsoft.AspNetCore.Http.HttpResults.BadRequest> when the input is invalid: | ||
|
|
||
| :::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Controllers/ValuesController.cs" id="snippet_1"::: | ||
|
|
||
| A problem details response is generated with the previous code when any of the following conditions apply: | ||
|
|
||
| * The `/api/values2/divide` endpoint is called with a zero denominator. | ||
| * The `/api/values2/squareroot` endpoint is called with a radicand less than zero. | ||
|
|
||
| The default problem details response body has the following `type`, `title`, and `status` values: | ||
|
|
||
| ```json | ||
| { | ||
| "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", | ||
| "title": "Bad Request", | ||
| "status": 400, | ||
| "traceId": "00-84c1fd4063c38d9f3900d06e56542d48-85d1d4-00" | ||
| } | ||
| ``` | ||
|
|
||
| <a name="pds7"></a> | ||
|
|
||
| ### Problem details service | ||
|
|
||
| The problem details service implements the <xref:Microsoft.AspNetCore.Http.IProblemDetailsService> interface, which supports creating [Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc7807.html). | ||
|
|
||
| The following middleware generates problem details HTTP responses when [`AddProblemDetails`](/dotnet/api/microsoft.extensions.dependencyinjection.problemdetailsservicecollectionextensions.addproblemdetails?view=aspnetcore-7.0&preserve-view=true) is called, except when not accepted by the client: | ||
|
|
||
| * <xref:Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware>: Generates a problem details response when a custom handler is not defined. | ||
| * <xref:Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware>: Generates a problem details response by default. | ||
| * [DeveloperExceptionPageMiddleware](#dep7): Generates a problem details response in development when `text/html` is not accepted. | ||
|
|
||
| The following code configures the app to generate a problem details response for all HTTP client and server error responses that ***don't have a body content yet***: | ||
|
|
||
| :::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Program.cs" id="snippet_apishort" highlight="4,8-9,13"::: | ||
|
|
||
| In the [Generate problem details from Middleware](#gpdm7) section of this article, an example is provided where the response has started and the problem details response is not returned. | ||
|
|
||
| Consider the API controller from the previous section, which returns <xref:Microsoft.AspNetCore.Http.HttpResults.BadRequest> when the input is invalid: | ||
|
|
||
| :::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Controllers/ValuesController.cs" id="snippet_1"::: | ||
|
|
||
| A problem details response is generated with the previous code when any of the following conditions apply: | ||
|
brunolins16 marked this conversation as resolved.
|
||
|
|
||
| * An invalid input is supplied. | ||
| * The URI has no matching endpoint. | ||
|
Rick-Anderson marked this conversation as resolved.
Rick-Anderson marked this conversation as resolved.
|
||
| * An unhandled exception occurs. | ||
|
|
||
| The automatic creation of a `ProblemDetails` for error status codes is disabled when the <xref:Microsoft.AspNetCore.Mvc.ApiBehaviorOptions.SuppressMapClientErrors%2A> property is set to `true`: | ||
|
|
||
| :::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Program.cs" id="snippet_disable" highlight="4,9"::: | ||
|
|
||
| Using the preceding code, when an API controller returns `BadRequest`, an [HTTP 400](https://developer.mozilla.org/docs/Web/HTTP/Status/400) response status is returned with no response body. `SuppressMapClientErrors` prevents a `ProblemDetails` response from being created, even when calling `WriteAsync` for an API Controller endpoint. `WriteAsync` is explained later in this article. | ||
|
|
||
| The next section shows how to customize the problem details response body to return a more helpful response. | ||
|
|
||
| <a name="cpd7"></a> | ||
|
|
||
| #### Customize problem details with `CustomizeProblemDetails` | ||
|
|
||
| The following code uses <xref:Microsoft.AspNetCore.Http.ProblemDetailsOptions> to set <xref:Microsoft.AspNetCore.Http.ProblemDetailsOptions.CustomizeProblemDetails>: | ||
|
|
||
| :::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Program.cs" id="snippet_api_controller" highlight="6"::: | ||
|
|
||
| The updated API controller: | ||
|
|
||
| :::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Controllers/ValuesController.cs" id="snippet" highlight="9-17,27-35"::: | ||
|
|
||
| The following code contains the `MathErrorFeature` and `MathErrorType`, which are used with the preceding sample: | ||
|
|
||
| :::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/MathErrorFeature.cs" ::: | ||
|
|
||
| A problem details response is generated with the previous code when any of the following conditions apply: | ||
|
|
||
| * The `/divide` endpoint is called with a zero denominator. | ||
| * The `/squareroot` endpoint is called with a radicand less than zero. | ||
| * The URI has no matching endpoint. | ||
|
|
||
| The problem details response body contains the following when either `squareroot` endpoint is called with a radicand less than zero: | ||
|
|
||
| ```json | ||
| { | ||
| "type": "https://en.wikipedia.org/wiki/Square_root", | ||
| "title": "Bad Input", | ||
| "status": 400, | ||
| "detail": "Negative or complex numbers are not allowed." | ||
| } | ||
| ``` | ||
|
|
||
| [View or download sample code](https://github.com/dotnet/AspNetCore.Docs.Samples/tree/main/fundamentals/middleware/problem-details-service) | ||
|
|
||
| <a name="gpdm7"></a> | ||
|
|
||
| #### Generate problem details from Middleware | ||
|
brunolins16 marked this conversation as resolved.
|
||
|
|
||
| An alternative approach to using <xref:Microsoft.AspNetCore.Http.ProblemDetailsOptions> to set <xref:Microsoft.AspNetCore.Http.ProblemDetailsOptions.CustomizeProblemDetails> is to set the <xref:Microsoft.AspNetCore.Http.ProblemDetailsContext.ProblemDetails> in middleware. A problem details response can be written by calling [`IProblemDetailsService.WriteAsync`](/dotnet/api/microsoft.aspnetcore.http.iproblemdetailsservice.writeasync?view=aspnetcore-7.0&preserve-view=true): | ||
|
|
||
| :::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Program.cs" id="snippet_middleware" highlight="5,19-40"::: | ||
|
|
||
| In the preceding code, the minimal API endpoints `/divide` and `/squareroot` return the expected custom problem response on error input. | ||
|
|
||
| The API controller endpoints return the default problem response on error input, not the custom problem response. The default problem response is returned because the API controller has written to the response stream, [Problem details for error status codes](/aspnet/core/web-api/#problem-details-for-error-status-codes-1), before [`IProblemDetailsService.WriteAsync`](https://github.com/dotnet/aspnetcore/blob/ce2db7ea0b161fc5eb35710fca6feeafeeac37bc/src/Http/Http.Extensions/src/ProblemDetailsService.cs#L24) is called and the response will not be written again. | ||
|
|
||
| The preceding `ValuesController` returns <xref:Microsoft.AspNetCore.Mvc.BadRequestResult>, which writes to the response stream and therefore prevents the custom problem response from being returned. | ||
|
|
||
| The following `Values3Controller` returns [`ControllerBase.Problem`](/dotnet/api/microsoft.aspnetcore.mvc.controllerbase.problem) so the expected custom problem result is returned: | ||
|
|
||
| :::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Controllers/ValuesController.cs" id="snippet3" highlight="16-21"::: | ||
|
Rick-Anderson marked this conversation as resolved.
|
||
|
|
||
| ### Produce a ProblemDetails payload for exceptions | ||
|
|
||
| Consider the following app: | ||
|
|
||
| :::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Program.cs" id="snippet_apishort" highlight="4,8"::: | ||
|
|
||
| In non-development environments, when an exception occurs, the following a standardized [ProblemDetails response](https://datatracker.ietf.org/doc/html/rfc7807) is returned to the client: | ||
|
|
||
| ```json | ||
| { | ||
| "type":"https://tools.ietf.org/html/rfc7231#section-6.6.1", | ||
| "title":"An error occurred while processing your request.", | ||
| "status":500,"traceId":"00-b644<snip>-00" | ||
| } | ||
| ``` | ||
|
|
||
| For most apps, the preceding code is all that for exceptions, however, the following section shows how get more detailed problem responses. | ||
|
|
||
| An alternative to a [custom exception handler page](xref:fundamentals/error-handling#exception-handler-page) is to provide a lambda to <xref:Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions.UseExceptionHandler%2A>. Using a lambda allows access to the error and writing a problem details response with [`IProblemDetailsService.WriteAsync`](/dotnet/api/microsoft.aspnetcore.http.iproblemdetailsservice.writeasync?view=aspnetcore-7.0&preserve-view=true): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the strategy for to content duplication? |
||
|
|
||
| :::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Program.cs" id="snippet_lambda" ::: | ||
|
|
||
| > [!WARNING] | ||
| > Do **not** serve sensitive error information to clients. Serving errors is a security risk. | ||
|
|
||
| [Hellang.Middleware.ProblemDetails](https://www.nuget.org/packages/Hellang.Middleware.ProblemDetails/) is a 3rd party problem details middleware Nuget package. | ||
|
|
||
| ### Implement `ProblemDetailsFactory` | ||
|
|
||
| MVC uses <xref:Microsoft.AspNetCore.Mvc.Infrastructure.ProblemDetailsFactory?displayProperty=fullName> to produce all instances of <xref:Microsoft.AspNetCore.Mvc.ProblemDetails> and <xref:Microsoft.AspNetCore.Mvc.ValidationProblemDetails>. This factory is used for: | ||
|
|
@@ -165,18 +310,11 @@ Use the <xref:Microsoft.AspNetCore.Mvc.ApiBehaviorOptions.ClientErrorMapping%2A> | |
|
|
||
| :::code language="csharp" source="handle-errors/samples/6.x/HandleErrorsSample/Snippets/Program.cs" id="snippet_ClientErrorMapping"::: | ||
|
|
||
| ## Custom Middleware to handle exceptions | ||
|
|
||
| The defaults in the exception handling middleware work well for most apps. For apps that require specialized exception handling, consider [customizing the exception handling middleware](xref:fundamentals/error-handling#exception-handler-lambda). | ||
|
|
||
| ### Produce a ProblemDetails payload for exceptions | ||
|
|
||
| ASP.NET Core doesn't produce a standardized error payload when an unhandled exception occurs. For scenarios where it's desirable to return a standardized [ProblemDetails response](https://datatracker.ietf.org/doc/html/rfc7807) to the client, the [ProblemDetails middleware](https://www.nuget.org/packages/Hellang.Middleware.ProblemDetails/) can be used to map exceptions and 404 responses to a [ProblemDetails](xref:web-api/handle-errors#pd) payload. The exception handling middleware can also be used to return a <xref:Microsoft.AspNetCore.Mvc.ProblemDetails> payload for unhandled exceptions. | ||
|
|
||
| ## Additional resources | ||
|
|
||
| * [How to Use ModelState Validation in ASP.NET Core Web API](https://code-maze.com/aspnetcore-modelstate-validation-web-api/) | ||
| * [View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/web-api/handle-errors/samples) ([How to download](xref:index#how-to-download-a-sample)) | ||
| * [View or download sample code](https://github.com/dotnet/AspNetCore.Docs.Samples/tree/main/fundamentals/middleware/problem-details-service) | ||
| * [Hellang.Middleware.ProblemDetails]](https://www.nuget.org/packages/Hellang.Middleware.ProblemDetails/) | ||
|
|
||
| :::moniker-end | ||
|
|
||
|
|
@@ -310,12 +448,12 @@ For web API controllers, MVC responds with a <xref:Microsoft.AspNetCore.Mvc.Vali | |
|
|
||
| ## Client error response | ||
|
|
||
| An *error result* is defined as a result with an HTTP status code of 400 or higher. For web API controllers, MVC transforms an error result to a produce a <xref:Microsoft.AspNetCore.Mvc.ProblemDetails>. | ||
| An *error result* is defined as a result with an HTTP status code of 400 or higher. For web API controllers, MVC transforms an error result to produce a <xref:Microsoft.AspNetCore.Mvc.ProblemDetails>. | ||
|
|
||
| The error response can be configured in one of the following ways: | ||
|
|
||
| 1. [Implement ProblemDetailsFactory](#implement-problemdetailsfactory) | ||
| 1. [Use ApiBehaviorOptions.ClientErrorMapping](#use-apibehavioroptionsclienterrormapping) | ||
| 1. Use [ApiBehaviorOptions.ClientErrorMapping](#use-apibehavioroptionsclienterrormapping) | ||
|
|
||
| ### Implement `ProblemDetailsFactory` | ||
|
|
||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.