14 KiB
title | author | description | monikerRange | ms.author | ms.custom | ms.date | uid |
---|---|---|---|---|---|---|---|
Handle errors in ASP.NET Core | rick-anderson | Discover how to handle errors in ASP.NET Core apps. | >= aspnetcore-2.1 | riande | mvc | 10/08/2019 | fundamentals/error-handling |
Handle errors in ASP.NET Core
By Tom Dykstra, Luke Latham, and Steve Smith
This article covers common approaches to handling errors in ASP.NET Core web apps. See xref:web-api/handle-errors for web APIs.
View or download sample code. (How to download.) The article includes instructions about how to set preprocessor directives (#if
, #endif
, #define
) in the sample app to enable different scenarios.
Developer Exception Page
The Developer Exception Page displays detailed information about request exceptions. The page is made available by the Microsoft.AspNetCore.Diagnostics package, which is in the Microsoft.AspNetCore.App metapackage. Add code to the Startup.Configure
method to enable the page when the app is running in the Development environment:
Place the call to xref:Microsoft.AspNetCore.Builder.DeveloperExceptionPageExtensions.UseDeveloperExceptionPage* before any middleware that you want to catch exceptions.
[!WARNING] Enable the Developer Exception Page only when the app is running in the Development environment. You don't want to share detailed exception information publicly when the app runs in production. For more information on configuring environments, see xref:fundamentals/environments.
The page includes the following information about the exception and the request:
- Stack trace
- Query string parameters (if any)
- Cookies (if any)
- Headers
To see the Developer Exception Page in the
sample app, use the DevEnvironment
preprocessor directive and select Trigger an exception on the home page.
Exception handler page
To configure a custom error handling page for the Production environment, use the Exception Handling Middleware. The middleware:
- Catches and logs exceptions.
- Re-executes the request in an alternate pipeline for the page or controller indicated. The request isn't re-executed if the response has started.
In the following example, xref:Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions.UseExceptionHandler* adds the Exception Handling Middleware in non-Development environments:
The Razor Pages app template provides an Error page (.cshtml) and xref:Microsoft.AspNetCore.Mvc.RazorPages.PageModel class (ErrorModel
) in the Pages folder. For an MVC app, the project template includes an Error action method and an Error view. Here's the action method:
[AllowAnonymous]
public IActionResult Error()
{
return View(new ErrorViewModel
{ RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
Don't decorate the error handler action method with HTTP method attributes, such as HttpGet
. Explicit verbs prevent some requests from reaching the method. Allow anonymous access to the method so that unauthenticated users are able to receive the error view.
Access the exception
Use xref:Microsoft.AspNetCore.Diagnostics.IExceptionHandlerPathFeature to access the exception and the original request path in an error handler controller or page:
[!WARNING] Do not serve sensitive error information to clients. Serving errors is a security risk.
To see the exception handling page in the sample app, use the ProdEnvironment
and ErrorHandlerPage
preprocessor directives, and select Trigger an exception on the home page.
Exception handler lambda
An alternative to a custom exception handler page is to provide a lambda to xref:Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions.UseExceptionHandler*. Using a lambda allows access to the error before returning the response.
Here's an example of using a lambda for exception handling:
[!WARNING] Do not serve sensitive error information from xref:Microsoft.AspNetCore.Diagnostics.IExceptionHandlerFeature or xref:Microsoft.AspNetCore.Diagnostics.IExceptionHandlerPathFeature to clients. Serving errors is a security risk.
To see the result of the exception handling lambda in the sample app, use the ProdEnvironment
and ErrorHandlerLambda
preprocessor directives, and select Trigger an exception on the home page.
UseStatusCodePages
By default, an ASP.NET Core app doesn't provide a status code page for HTTP status codes, such as 404 - Not Found. The app returns a status code and an empty response body. To provide status code pages, use Status Code Pages middleware.
The middleware is made available by the Microsoft.AspNetCore.Diagnostics package, which is in the Microsoft.AspNetCore.App metapackage.
To enable default text-only handlers for common error status codes, call xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePages* in the Startup.Configure
method:
Call UseStatusCodePages
before request handling middleware (for example, Static File Middleware and MVC Middleware).
Here's an example of text displayed by the default handlers:
Status Code: 404; Not Found
To see one of the various status code page formats in the sample app, use one of the preprocessor directives that begin with StatusCodePages
, and select Trigger a 404 on the home page.
UseStatusCodePages with format string
To customize the response content type and text, use the overload of xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePages* that takes a content type and format string:
UseStatusCodePages with lambda
To specify custom error-handling and response-writing code, use the overload of xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePages* that takes a lambda expression:
UseStatusCodePagesWithRedirects
The xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePagesWithRedirects* extension method:
- Sends a 302 - Found status code to the client.
- Redirects the client to the location provided in the URL template.
The URL template can include a {0}
placeholder for the status code, as shown in the example. If the URL template starts with a tilde (~), the tilde is replaced by the app's PathBase
. If you point to an endpoint within the app, create an MVC view or Razor page for the endpoint. For a Razor Pages example, see Pages/StatusCode.cshtml in the sample app.
This method is commonly used when the app:
- Should redirect the client to a different endpoint, usually in cases where a different app processes the error. For web apps, the client's browser address bar reflects the redirected endpoint.
- Shouldn't preserve and return the original status code with the initial redirect response.
UseStatusCodePagesWithReExecute
The xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePagesWithReExecute* extension method:
- Returns the original status code to the client.
- Generates the response body by re-executing the request pipeline using an alternate path.
If you point to an endpoint within the app, create an MVC view or Razor page for the endpoint. For a Razor Pages example, see Pages/StatusCode.cshtml in the sample app.
This method is commonly used when the app should:
- Process the request without redirecting to a different endpoint. For web apps, the client's browser address bar reflects the originally requested endpoint.
- Preserve and return the original status code with the response.
The URL and query string templates may include a placeholder ({0}
) for the status code. The URL template must start with a slash (/
). When using a placeholder in the path, confirm that the endpoint (page or controller) can process the path segment. For example, a Razor Page for errors should accept the optional path segment value with the @page
directive:
@page "{code?}"
The endpoint that processes the error can get the original URL that generated the error, as shown in the following example:
Disable status code pages
To disable status code pages for an MVC controller or action method, use the [SkipStatusCodePages] attribute.
To disable status code pages for specific requests in a Razor Pages handler method or in an MVC controller, use xref:Microsoft.AspNetCore.Diagnostics.IStatusCodePagesFeature:
var statusCodePagesFeature = HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature != null)
{
statusCodePagesFeature.Enabled = false;
}
Exception-handling code
Code in exception handling pages can throw exceptions. It's often a good idea for production error pages to consist of purely static content.
Response headers
Once the headers for a response are sent:
- The app can't change the response's status code.
- Any exception pages or handlers can't run. The response must be completed or the connection aborted.
Server exception handling
In addition to the exception handling logic in your app, the HTTP server implementation can handle some exceptions. If the server catches an exception before response headers are sent, the server sends a 500 - Internal Server Error response without a response body. If the server catches an exception after response headers are sent, the server closes the connection. Requests that aren't handled by your app are handled by the server. Any exception that occurs when the server is handling the request is handled by the server's exception handling. The app's custom error pages, exception handling middleware, and filters don't affect this behavior.
Startup exception handling
Only the hosting layer can handle exceptions that take place during app startup. The host can be configured to capture startup errors and capture detailed errors.
The hosting layer can show an error page for a captured startup error only if the error occurs after host address/port binding. If binding fails:
- The hosting layer logs a critical exception.
- The dotnet process crashes.
- No error page is displayed when the HTTP server is Kestrel.
When running on IIS (or Azure App Service) or IIS Express, a 502.5 - Process Failure is returned by the ASP.NET Core Module if the process can't start. For more information, see xref:test/troubleshoot-azure-iis.
Database error page
Database Error Page Middleware captures database-related exceptions that can be resolved by using Entity Framework migrations. When these exceptions occur, an HTML response with details of possible actions to resolve the issue is generated. This page should be enabled only in the Development environment. Enable the page by adding code to Startup.Configure
:
if (env.IsDevelopment())
{
app.UseDatabaseErrorPage();
}
Exception filters
In MVC apps, exception filters can be configured globally or on a per-controller or per-action basis. In Razor Pages apps, they can be configured globally or per page model. These filters handle any unhandled exception that occurs during the execution of a controller action or another filter. For more information, see xref:mvc/controllers/filters#exception-filters.
[!TIP] Exception filters are useful for trapping exceptions that occur within MVC actions, but they're not as flexible as the Exception Handling Middleware. We recommend using the middleware. Use filters only where you need to perform error handling differently based on which MVC action is chosen.
Model state errors
For information about how to handle model state errors, see Model binding and Model validation.