Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
57155d6
moniker prep
Rick-Anderson Sep 9, 2022
f082a15
Problem details service /2
Rick-Anderson Sep 15, 2022
a17a7d0
Merge branch 'main' into nMonPrep
Rick-Anderson Sep 15, 2022
32196f9
Problem details service /2
Rick-Anderson Sep 15, 2022
23e2041
work
Rick-Anderson Sep 20, 2022
092e444
work
Rick-Anderson Sep 20, 2022
9bc9ba0
Update docker-compose-https.md
Rick-Anderson Sep 20, 2022
7178277
work
Rick-Anderson Sep 20, 2022
954bc2f
Merge branch 'nMonPrep' of https://github.com/dotnet/AspNetCore.Docs …
Rick-Anderson Sep 20, 2022
c251998
work
Rick-Anderson Sep 20, 2022
8465f6d
work
Rick-Anderson Sep 20, 2022
102a9c9
work
Rick-Anderson Sep 20, 2022
9b91236
work
Rick-Anderson Sep 20, 2022
e143b0c
work
Rick-Anderson Sep 20, 2022
4d46420
work
Rick-Anderson Sep 20, 2022
8294896
work
Rick-Anderson Sep 21, 2022
456bcd7
work
Rick-Anderson Sep 21, 2022
adab4de
work
Rick-Anderson Sep 21, 2022
9e14ac2
work
Rick-Anderson Sep 21, 2022
db02f54
work
Rick-Anderson Sep 21, 2022
275beaa
work
Rick-Anderson Sep 21, 2022
05780d3
work
Rick-Anderson Sep 21, 2022
cfd0f8a
work
Rick-Anderson Sep 21, 2022
e2d0b67
work
Rick-Anderson Sep 21, 2022
3850735
Apply suggestions from code review
Rick-Anderson Sep 22, 2022
d293e41
react to feedback
Rick-Anderson Sep 23, 2022
d439c24
react to feedback
Rick-Anderson Sep 23, 2022
1a5d61c
react to feedback
Rick-Anderson Sep 23, 2022
f6ea501
react to feedback
Rick-Anderson Sep 23, 2022
70e65ff
Update aspnetcore/web-api/handle-errors.md
Rick-Anderson Sep 23, 2022
4acc412
react to feedback
Rick-Anderson Sep 23, 2022
eb561a5
react to feedback
Rick-Anderson Sep 24, 2022
02db364
Apply suggestions from code review
Rick-Anderson Sep 26, 2022
584825c
react to feedback
Rick-Anderson Sep 27, 2022
1120a9f
react to feedback
Rick-Anderson Sep 27, 2022
e3163b0
react to feedback
Rick-Anderson Sep 27, 2022
05e1fa2
react to feedback
Rick-Anderson Sep 27, 2022
302ba16
react to feedback
Rick-Anderson Sep 27, 2022
b11dc6d
react to feedback
Rick-Anderson Sep 27, 2022
ac27e7f
react to feedback
Rick-Anderson Sep 28, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion aspnetcore/security/docker-compose-https.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Hosting ASP.NET Core image in container using docker compose with HTTPS
author: ravipal
description: Learn how to host ASP.NET Core Images with Docker Compose over HTTPS
monikerRange: '>= aspnetcore-2.1'
ms.author: ravipal
ms.author: riande
ms.custom: mvc
ms.date: 03/28/2020
uid: security/docker-compose-https
Expand Down
166 changes: 152 additions & 14 deletions aspnetcore/web-api/handle-errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -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
Comment thread
Rick-Anderson marked this conversation as resolved.

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:
Comment thread
brunolins16 marked this conversation as resolved.

* An invalid input is supplied.
* The URI has no matching endpoint.
Comment thread
Rick-Anderson marked this conversation as resolved.
Comment thread
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
Comment thread
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":::
Comment thread
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):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The 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:
Expand All @@ -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

Expand Down Expand Up @@ -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`

Expand Down