Asp net core 404 ошибка

I am using the middle-ware below to set up error pages for HTTP status codes 400 to 599. So visiting /error/400 shows a 400 Bad Request error page.

application.UseStatusCodePagesWithReExecute("/error/{0}");

[Route("[controller]")]
public class ErrorController : Controller
{
    [HttpGet("{statusCode}")]
    public IActionResult Error(int statusCode)
    {
        this.Response.StatusCode = statusCode;
        return this.View(statusCode);
    }
}

However, visiting /this-page-does-not-exist results in a generic IIS 404 Not Found error page.

Is there a way to handle requests that do not match any routes? How can I handle this type of request before IIS takes over? Ideally I would like to forward the request to /error/404 so that my error controller can handle it.

In ASP.NET 4.6 MVC 5, we had to use the httpErrors section in the Web.config file to do this.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
      <remove statusCode="404" />
      <error statusCode="404" responseMode="ExecuteURL" path="/error/404/" />
    </httpErrors>
  </system.webServer>
</configuration>

asked Jul 24, 2015 at 9:10

Muhammad Rehan Saeed's user avatar

6

One of the best tutorials I found is this: https://joonasw.net/view/custom-error-pages

The summary is here:

1.
First add a controller like ErrorController then add this action to it:

[Route("404")]
public IActionResult PageNotFound()
{
    string originalPath = "unknown";
    if (HttpContext.Items.ContainsKey("originalPath"))
    {
        originalPath = HttpContext.Items["originalPath"] as string;
    }
    return View();
}

Note: You can add the action to another existing controller like HomeController.

2.
Now add the PageNotFound.cshtml view. Something like this:

@{
    ViewBag.Title = "404";
}

<h1>404 - Page not found</h1>

<p>Oops, better check that URL.</p>

3.
And the important part is here. Add this code to Startup class, inside Configure method:

app.Use(async (ctx, next) =>
{
    await next();

    if(ctx.Response.StatusCode == 404 && !ctx.Response.HasStarted)
    {
        //Re-execute the request so the user gets the error page
        string originalPath = ctx.Request.Path.Value;
        ctx.Items["originalPath"] = originalPath;
        ctx.Request.Path = "/error/404";
        await next();
    }
});

Note that it must be added before routing configs like app.UseEndpoints....

answered Jun 10, 2020 at 8:29

Mahdi Ataollahi's user avatar

Mahdi AtaollahiMahdi Ataollahi

4,4544 gold badges30 silver badges38 bronze badges

3

Based on this SO item, IIS gets the 404 (and therefore handles it) before it reaches UseStatusCodePagesWithReExecute.

Have you tried this: https://github.com/aspnet/Diagnostics/issues/144? It suggests terminating the request that received a 404 so it does not go to IIS to handle. And here’s the code to add to your Startup to do so:

app.Run(context =>
{
   context.Response.StatusCode = 404;
   return Task.FromResult(0);
});

This appears to be an IIS-only issue.

Community's user avatar

answered Jul 27, 2015 at 4:22

Frank Fajardo's user avatar

Frank FajardoFrank Fajardo

6,9191 gold badge28 silver badges47 bronze badges

5

You can use fallback in EndPoint in asp.net core Like below (inside app.UseEndpoints) and with razor pages (NotFound is a razor page in Pages folder instead controller)

 endpoints.MapRazorPages();
            
 endpoints.MapFallback( context => {
    context.Response.Redirect("/NotFound");
    return Task.CompletedTask;
  });

answered Mar 29, 2021 at 11:54

Shojaeddin's user avatar

ShojaeddinShojaeddin

1,8211 gold badge18 silver badges16 bronze badges

1

After working on few hours for handling 500 and 404 errors, I have implemented below given solution.

For handling 500 Server Side Errors you can use app.UseExceptionHandler middleware but app.UseExceptionHandler middleware only handles unhandled exceptions while 404 isn’t an exception. For handling 404 errors I’ve designed another custom middleware which is checking response status code and if it is 404 then returning user to my custom 404 error page.

if (env.IsDevelopment())
   {
       app.UseDeveloperExceptionPage();
   }
   else
   {
       //Hnadle unhandled exceptions 500 erros
       app.UseExceptionHandler("/Pages500");
       //Handle 404 erros
       app.Use(async (ctx, next) =>
       {
           await next();
           if (ctx.Response.StatusCode == 404 && !ctx.Response.HasStarted)
           {
               //Re-execute the request so the user gets the error page
               ctx.Request.Path = "/Pages404";
               await next();
           }
       });
   }

Note: You must add app.UseExceptionHandler("/Pages500"); middleware at the starting of your Configure method so that it can handle exceptions from all middlewares. The custom middleware can be placed any ware before app.UseEndpoins middleware but still, it’s good to place in the beginning of Configure method.
/Pages500 and /Pages404 urls are my custom pages, you can design for your application.

answered Jul 16, 2021 at 4:25

habib's user avatar

habibhabib

2,3255 gold badges25 silver badges41 bronze badges

Asp.net core 3.1 and 5

in your HomeController.cs :

public class HomeController : Controller
{
   [Route("/NotFound")]
   public IActionResult PageNotFound()
   {
      return View();
   }
}

in Startup.cs > ConfigureServices method:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
   app.Use(async (context, next) =>
   {
      await next();
      if (context.Response.StatusCode == 404)
      {
         context.Request.Path = "/NotFound";
         await next();
      }
   });
   
   app.UseHttpsRedirection();
   app.UseStaticFiles();
}

answered Jun 19, 2021 at 10:49

Reza Ahmadi's user avatar

title author description monikerRange ms.author ms.custom ms.date uid

Handle errors in ASP.NET Core

tdykstra

Discover how to handle errors in ASP.NET Core apps.

>= aspnetcore-3.1

riande

mvc

01/18/2023

fundamentals/error-handling

Handle errors in ASP.NET Core

:::moniker range=»>= aspnetcore-7.0″

By Tom Dykstra

This article covers common approaches to handling errors in ASP.NET Core web apps. See xref:web-api/handle-errors for web APIs.

Developer exception page

The Developer Exception Page displays detailed information about unhandled request exceptions. ASP.NET Core apps enable the developer exception page by default when both:

  • Running in the Development environment.
  • App created with the current templates, that is, using WebApplication.CreateBuilder. Apps created using the WebHost.CreateDefaultBuilder must enable the developer exception page by calling app.UseDeveloperExceptionPage in Configure.

The developer exception page runs early in the middleware pipeline, so that it can catch unhandled exceptions thrown in middleware that follows.

Detailed exception information shouldn’t be displayed publicly when the app runs in the Production environment. For more information on configuring environments, see xref:fundamentals/environments.

The Developer Exception Page can include the following information about the exception and the request:

  • Stack trace
  • Query string parameters, if any
  • Cookies, if any
  • Headers

The Developer Exception Page isn’t guaranteed to provide any information. Use Logging for complete error information.

Exception handler page

To configure a custom error handling page for the Production environment, call xref:Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions.UseExceptionHandler%2A. This exception handling middleware:

  • Catches and logs unhandled exceptions.
  • Re-executes the request in an alternate pipeline using the path indicated. The request isn’t re-executed if the response has started. The template-generated code re-executes the request using the /Error path.

[!WARNING]
If the alternate pipeline throws an exception of its own, Exception Handling Middleware rethrows the original exception.

Since this middleware can re-execute the request pipeline:

  • Middlewares need to handle reentrancy with the same request. This normally means either cleaning up their state after calling _next or caching their processing on the HttpContext to avoid redoing it. When dealing with the request body, this either means buffering or caching the results like the Form reader.
  • For the xref:Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions.UseExceptionHandler(Microsoft.AspNetCore.Builder.IApplicationBuilder,System.String) overload that is used in templates, only the request path is modified, and the route data is cleared. Request data such as headers, method, and items are all reused as-is.
  • Scoped services remain the same.

In the following example, xref:Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions.UseExceptionHandler%2A adds the exception handling middleware in non-Development environments:

:::code language=»csharp» source=»error-handling/samples/7.x/ErrorHandlingSample/Program.cs» id=»snippet_UseExceptionHandler» highlight=»3,5″:::

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 for the Home controller.

The exception handling middleware re-executes the request using the original HTTP method. If an error handler endpoint is restricted to a specific set of HTTP methods, it runs only for those HTTP methods. For example, an MVC controller action that uses the [HttpGet] attribute runs only for GET requests. To ensure that all requests reach the custom error handling page, don’t restrict them to a specific set of HTTP methods.

To handle exceptions differently based on the original HTTP method:

  • For Razor Pages, create multiple handler methods. For example, use OnGet to handle GET exceptions and use OnPost to handle POST exceptions.
  • For MVC, apply HTTP verb attributes to multiple actions. For example, use [HttpGet] to handle GET exceptions and use [HttpPost] to handle POST exceptions.

To allow unauthenticated users to view the custom error handling page, ensure that it supports anonymous access.

Access the exception

Use xref:Microsoft.AspNetCore.Diagnostics.IExceptionHandlerPathFeature to access the exception and the original request path in an error handler. The following example uses IExceptionHandlerPathFeature to get more information about the exception that was thrown:

:::code language=»csharp» source=»error-handling/samples/7.x/ErrorHandlingSample/Pages/Error.cshtml.cs» id=»snippet_Class» highlight=»15-27″:::

[!WARNING]
Do not serve sensitive error information to clients. Serving errors is a security risk.

Exception handler lambda

An alternative to a custom exception handler page is to provide a lambda to xref:Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions.UseExceptionHandler%2A. Using a lambda allows access to the error before returning the response.

The following code uses a lambda for exception handling:

:::code language=»csharp» source=»error-handling/samples/7.x/ErrorHandlingSample/Snippets/Program.cs» id=»snippet_UseExceptionHandlerInline» highlight=»5-29″:::

[!WARNING]
Do not serve sensitive error information to clients. Serving errors is a security risk.

UseStatusCodePages

By default, an ASP.NET Core app doesn’t provide a status code page for HTTP error status codes, such as 404 — Not Found. When the app sets an HTTP 400-599 error status code that doesn’t have a body, it returns the status code and an empty response body. To enable default text-only handlers for common error status codes, call xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePages%2A in Program.cs:

:::code language=»csharp» source=»error-handling/samples/7.x/ErrorHandlingSample/Snippets/Program.cs» id=»snippet_UseStatusCodePages» highlight=»9″:::

Call UseStatusCodePages before request handling middleware. For example, call UseStatusCodePages before the Static File Middleware and the Endpoints Middleware.

When UseStatusCodePages isn’t used, navigating to a URL without an endpoint returns a browser-dependent error message indicating the endpoint can’t be found. When UseStatusCodePages is called, the browser returns the following response:

Status Code: 404; Not Found

UseStatusCodePages isn’t typically used in production because it returns a message that isn’t useful to users.

[!NOTE]
The status code pages middleware does not catch exceptions. To provide a custom error handling page, use the exception handler page.

UseStatusCodePages with format string

To customize the response content type and text, use the overload of xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePages%2A that takes a content type and format string:

:::code language=»csharp» source=»error-handling/samples/7.x/ErrorHandlingSample/Snippets/Program.cs» id=»snippet_UseStatusCodePagesContent» highlight=»10″:::

In the preceding code, {0} is a placeholder for the error code.

UseStatusCodePages with a format string isn’t typically used in production because it returns a message that isn’t useful to users.

UseStatusCodePages with lambda

To specify custom error-handling and response-writing code, use the overload of xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePages%2A that takes a lambda expression:

:::code language=»csharp» source=»error-handling/samples/7.x/ErrorHandlingSample/Snippets/Program.cs» id=»snippet_UseStatusCodePagesInline» highlight=»9-16″:::

UseStatusCodePages with a lambda isn’t typically used in production because it returns a message that isn’t useful to users.

UseStatusCodePagesWithRedirects

The xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePagesWithRedirects%2A extension method:

  • Sends a 302 — Found status code to the client.
  • Redirects the client to the error handling endpoint provided in the URL template. The error handling endpoint typically displays error information and returns HTTP 200.

:::code language=»csharp» source=»error-handling/samples/7.x/ErrorHandlingSample/Snippets/Program.cs» id=»snippet_UseStatusCodePagesRedirect» highlight=»9″:::

The URL template can include a {0} placeholder for the status code, as shown in the preceding code. If the URL template starts with ~ (tilde), the ~ is replaced by the app’s PathBase. When specifying an endpoint in the app, create an MVC view or Razor page for the endpoint.

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%2A extension method:

  • Generates the response body by re-executing the request pipeline using an alternate path.
  • Does not alter the status code before or after re-executing the pipeline.

The new pipeline execution may alter the response’s status code, as the new pipeline has full control of the status code. If the new pipeline does not alter the status code, the original status code will be sent to the client.

:::code language=»csharp» source=»error-handling/samples/7.x/ErrorHandlingSample/Snippets/Program.cs» id=»snippet_UseStatusCodePagesReExecute» highlight=»9″:::

If an endpoint within the app is specified, create an MVC view or Razor page for the endpoint.

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 template must start with / and may include a placeholder {0} for the status code. To pass the status code as a query-string parameter, pass a second argument into UseStatusCodePagesWithReExecute. For example:

:::code language=»csharp» source=»error-handling/samples/7.x/ErrorHandlingSample/Snippets/Program.cs» id=»snippet_UseStatusCodePagesReExecuteQueryString»:::

The endpoint that processes the error can get the original URL that generated the error, as shown in the following example:

:::code language=»csharp» source=»error-handling/samples/7.x/ErrorHandlingSample/Pages/StatusCode.cshtml.cs» id=»snippet_Class» highlight=»12-21″:::

Since this middleware can re-execute the request pipeline:

  • Middlewares need to handle reentrancy with the same request. This normally means either cleaning up their state after calling _next or caching their processing on the HttpContext to avoid redoing it. When dealing with the request body, this either means buffering or caching the results like the Form reader.
  • Scoped services remain the same.

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:

:::code language=»csharp» source=»error-handling/samples/7.x/ErrorHandlingSample/Snippets/Pages/Index.cshtml.cs» id=»snippet_OnGet»:::

Exception-handling code

Code in exception handling pages can also throw exceptions. Production error pages should be tested thoroughly and take extra care to avoid throwing exceptions of their own.

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 an 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 the 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

The Database developer page exception filter xref:Microsoft.Extensions.DependencyInjection.DatabaseDeveloperPageExceptionFilterServiceExtensions.AddDatabaseDeveloperPageExceptionFilter%2A captures database-related exceptions that can be resolved by using Entity Framework Core migrations. When these exceptions occur, an HTML response is generated with details of possible actions to resolve the issue. This page is enabled only in the Development environment. The following code adds the Database developer page exception filter:

:::code language=»csharp» source=»error-handling/samples/7.x/ErrorHandlingSample/Program.cs» id=»snippet_AddDatabaseDeveloperPageExceptionFilter» highlight=»3″:::

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 exceptions that occur during the execution of a controller action or another filter. For more information, see xref:mvc/controllers/filters#exception-filters.

Exception filters are useful for trapping exceptions that occur within MVC actions, but they’re not as flexible as the built-in exception handling middleware, xref:Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions.UseExceptionHandler%2A. We recommend using UseExceptionHandler, unless 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.

Problem details

[!INCLUDE]

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=»error-handling/samples/7.x/ErrorHandlingSample/Snippets/Program.cs» id=»snippet_AddProblemDetails» highlight=»3″:::

The next section shows how to customize the problem details response body.

Customize problem details

The automatic creation of a ProblemDetails can be customized using any of the following options:

  1. Use ProblemDetailsOptions.CustomizeProblemDetails
  2. Use a custom IProblemDetailsWriter
  3. Call the IProblemDetailsService in a middleware

CustomizeProblemDetails operation

The generated problem details can be customized using xref:Microsoft.AspNetCore.Http.ProblemDetailsOptions.CustomizeProblemDetails, and the customizations are applied to all auto-generated problem details.

The following code uses xref:Microsoft.AspNetCore.Http.ProblemDetailsOptions to set xref:Microsoft.AspNetCore.Http.ProblemDetailsOptions.CustomizeProblemDetails:

:::code language=»csharp» source=»error-handling/samples/7.x/ErrorHandlingSample/Snippets/Program.cs» id=»snippet_CustomizeProblemDetails» highlight=»3-5″:::

For example, an HTTP Status 400 Bad Request endpoint result produces the following problem details response body:

{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "Bad Request",
  "status": 400,
  "nodeId": "my-machine-name"
}

Custom IProblemDetailsWriter

An xref:Microsoft.AspNetCore.Http.IProblemDetailsWriter implementation can be created for advanced customizations.

:::code language=»csharp» source=»~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/SampleProblemDetailsWriter.cs» :::

Note: When using a custom IProblemDetailsWriter, the custom IProblemDetailsWriter must be registered before calling xref:Microsoft.Extensions.DependencyInjection.MvcServiceCollectionExtensions.AddRazorPages%2A, xref:Microsoft.Extensions.DependencyInjection.MvcServiceCollectionExtensions.AddControllers%2A, or xref:Microsoft.Extensions.DependencyInjection.MvcServiceCollectionExtensions.AddControllersWithViews%2A:

:::code language=»csharp» source=»~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Program.cs» id=»snippet_sampleproblemdetailswriter» :::

Problem details from Middleware

An alternative approach to using xref:Microsoft.AspNetCore.Http.ProblemDetailsOptions with 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:

:::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, before IProblemDetailsService.WriteAsync is called and the response is not written again.

The following ValuesController returns xref:Microsoft.AspNetCore.Mvc.BadRequestResult, which writes to the response stream and therefore prevents the custom problem response from being returned.

:::code language=»csharp» source=»~/../AspNetCore.Docs.Samples/fundamentals/middleware/problem-details-service/Controllers/ValuesController.cs» id=»snippet» highlight=»9-17,27-35″:::

The following Values3Controller returns 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″:::

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 is a standard ProblemDetails response that is returned to the client:

{
"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’s needed for exceptions. However, the following section shows how to get more detailed problem responses.

An alternative to a custom 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:

:::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.

An alternative approach to generate problem details is to use the third-party NuGet package Hellang.Middleware.ProblemDetails that can be used to map exceptions and client errors to problem details.

Additional resources

  • View or download sample code (how to download)
  • xref:test/troubleshoot-azure-iis
  • xref:host-and-deploy/azure-iis-errors-reference

:::moniker-end

:::moniker range=»= aspnetcore-6.0″

By Tom Dykstra

This article covers common approaches to handling errors in ASP.NET Core web apps. See xref:web-api/handle-errors for web APIs.

Developer exception page

The Developer Exception Page displays detailed information about unhandled request exceptions. ASP.NET Core apps enable the developer exception page by default when both:

  • Running in the Development environment.
  • App created with the current templates, that is, using WebApplication.CreateBuilder. Apps created using the WebHost.CreateDefaultBuilder must enable the developer exception page by calling app.UseDeveloperExceptionPage in Configure.

The developer exception page runs early in the middleware pipeline, so that it can catch unhandled exceptions thrown in middleware that follows.

Detailed exception information shouldn’t be displayed publicly when the app runs in the Production environment. For more information on configuring environments, see xref:fundamentals/environments.

The Developer Exception Page can include the following information about the exception and the request:

  • Stack trace
  • Query string parameters, if any
  • Cookies, if any
  • Headers

The Developer Exception Page isn’t guaranteed to provide any information. Use Logging for complete error information.

Exception handler page

To configure a custom error handling page for the Production environment, call xref:Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions.UseExceptionHandler%2A. This exception handling middleware:

  • Catches and logs unhandled exceptions.
  • Re-executes the request in an alternate pipeline using the path indicated. The request isn’t re-executed if the response has started. The template-generated code re-executes the request using the /Error path.

[!WARNING]
If the alternate pipeline throws an exception of its own, Exception Handling Middleware rethrows the original exception.

In the following example, xref:Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions.UseExceptionHandler%2A adds the exception handling middleware in non-Development environments:

:::code language=»csharp» source=»error-handling/samples/6.x/ErrorHandlingSample/Program.cs» id=»snippet_UseExceptionHandler» highlight=»3,5″:::

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 for the Home controller.

The exception handling middleware re-executes the request using the original HTTP method. If an error handler endpoint is restricted to a specific set of HTTP methods, it runs only for those HTTP methods. For example, an MVC controller action that uses the [HttpGet] attribute runs only for GET requests. To ensure that all requests reach the custom error handling page, don’t restrict them to a specific set of HTTP methods.

To handle exceptions differently based on the original HTTP method:

  • For Razor Pages, create multiple handler methods. For example, use OnGet to handle GET exceptions and use OnPost to handle POST exceptions.
  • For MVC, apply HTTP verb attributes to multiple actions. For example, use [HttpGet] to handle GET exceptions and use [HttpPost] to handle POST exceptions.

To allow unauthenticated users to view the custom error handling page, ensure that it supports anonymous access.

Access the exception

Use xref:Microsoft.AspNetCore.Diagnostics.IExceptionHandlerPathFeature to access the exception and the original request path in an error handler. The following example uses IExceptionHandlerPathFeature to get more information about the exception that was thrown:

:::code language=»csharp» source=»error-handling/samples/6.x/ErrorHandlingSample/Pages/Error.cshtml.cs» id=»snippet_Class» highlight=»15-27″:::

[!WARNING]
Do not serve sensitive error information to clients. Serving errors is a security risk.

Exception handler lambda

An alternative to a custom exception handler page is to provide a lambda to xref:Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions.UseExceptionHandler%2A. Using a lambda allows access to the error before returning the response.

The following code uses a lambda for exception handling:

:::code language=»csharp» source=»error-handling/samples/6.x/ErrorHandlingSample/Snippets/Program.cs» id=»snippet_UseExceptionHandlerInline» highlight=»5-29″:::

[!WARNING]
Do not serve sensitive error information to clients. Serving errors is a security risk.

UseStatusCodePages

By default, an ASP.NET Core app doesn’t provide a status code page for HTTP error status codes, such as 404 — Not Found. When the app sets an HTTP 400-599 error status code that doesn’t have a body, it returns the status code and an empty response body. To enable default text-only handlers for common error status codes, call xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePages%2A in Program.cs:

:::code language=»csharp» source=»error-handling/samples/6.x/ErrorHandlingSample/Snippets/Program.cs» id=»snippet_UseStatusCodePages» highlight=»9″:::

Call UseStatusCodePages before request handling middleware. For example, call UseStatusCodePages before the Static File Middleware and the Endpoints Middleware.

When UseStatusCodePages isn’t used, navigating to a URL without an endpoint returns a browser-dependent error message indicating the endpoint can’t be found. When UseStatusCodePages is called, the browser returns the following response:

Status Code: 404; Not Found

UseStatusCodePages isn’t typically used in production because it returns a message that isn’t useful to users.

[!NOTE]
The status code pages middleware does not catch exceptions. To provide a custom error handling page, use the exception handler page.

UseStatusCodePages with format string

To customize the response content type and text, use the overload of xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePages%2A that takes a content type and format string:

:::code language=»csharp» source=»error-handling/samples/6.x/ErrorHandlingSample/Snippets/Program.cs» id=»snippet_UseStatusCodePagesContent» highlight=»10″:::

In the preceding code, {0} is a placeholder for the error code.

UseStatusCodePages with a format string isn’t typically used in production because it returns a message that isn’t useful to users.

UseStatusCodePages with lambda

To specify custom error-handling and response-writing code, use the overload of xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePages%2A that takes a lambda expression:

:::code language=»csharp» source=»error-handling/samples/6.x/ErrorHandlingSample/Snippets/Program.cs» id=»snippet_UseStatusCodePagesInline» highlight=»9-16″:::

UseStatusCodePages with a lambda isn’t typically used in production because it returns a message that isn’t useful to users.

UseStatusCodePagesWithRedirects

The xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePagesWithRedirects%2A extension method:

  • Sends a 302 — Found status code to the client.
  • Redirects the client to the error handling endpoint provided in the URL template. The error handling endpoint typically displays error information and returns HTTP 200.

:::code language=»csharp» source=»error-handling/samples/6.x/ErrorHandlingSample/Snippets/Program.cs» id=»snippet_UseStatusCodePagesRedirect» highlight=»9″:::

The URL template can include a {0} placeholder for the status code, as shown in the preceding code. If the URL template starts with ~ (tilde), the ~ is replaced by the app’s PathBase. When specifying an endpoint in the app, create an MVC view or Razor page for the endpoint.

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%2A extension method:

  • Returns the original status code to the client.
  • Generates the response body by re-executing the request pipeline using an alternate path.

:::code language=»csharp» source=»error-handling/samples/6.x/ErrorHandlingSample/Snippets/Program.cs» id=»snippet_UseStatusCodePagesReExecute» highlight=»9″:::

If an endpoint within the app is specified, create an MVC view or Razor page for the endpoint.

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 template must start with / and may include a placeholder {0} for the status code. To pass the status code as a query-string parameter, pass a second argument into UseStatusCodePagesWithReExecute. For example:

:::code language=»csharp» source=»error-handling/samples/6.x/ErrorHandlingSample/Snippets/Program.cs» id=»snippet_UseStatusCodePagesReExecuteQueryString»:::

The endpoint that processes the error can get the original URL that generated the error, as shown in the following example:

:::code language=»csharp» source=»error-handling/samples/6.x/ErrorHandlingSample/Pages/StatusCode.cshtml.cs» id=»snippet_Class» highlight=»12-21″:::

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:

:::code language=»csharp» source=»error-handling/samples/6.x/ErrorHandlingSample/Snippets/Pages/Index.cshtml.cs» id=»snippet_OnGet»:::

Exception-handling code

Code in exception handling pages can also throw exceptions. Production error pages should be tested thoroughly and take extra care to avoid throwing exceptions of their own.

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 an 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 the 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

The Database developer page exception filter xref:Microsoft.Extensions.DependencyInjection.DatabaseDeveloperPageExceptionFilterServiceExtensions.AddDatabaseDeveloperPageExceptionFilter%2A captures database-related exceptions that can be resolved by using Entity Framework Core migrations. When these exceptions occur, an HTML response is generated with details of possible actions to resolve the issue. This page is enabled only in the Development environment. The following code adds the Database developer page exception filter:

:::code language=»csharp» source=»error-handling/samples/6.x/ErrorHandlingSample/Program.cs» id=»snippet_AddDatabaseDeveloperPageExceptionFilter» highlight=»3″:::

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 exceptions that occur during the execution of a controller action or another filter. For more information, see xref:mvc/controllers/filters#exception-filters.

Exception filters are useful for trapping exceptions that occur within MVC actions, but they’re not as flexible as the built-in exception handling middleware, xref:Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions.UseExceptionHandler%2A. We recommend using UseExceptionHandler, unless 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.

Additional resources

  • View or download sample code (how to download)
  • xref:test/troubleshoot-azure-iis
  • xref:host-and-deploy/azure-iis-errors-reference

:::moniker-end

:::moniker range=»>= aspnetcore-5.0 < aspnetcore-6.0″

By Kirk Larkin, Tom Dykstra, 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 network tab on the F12 browser developer tools is useful when testing the sample app.

Developer Exception Page

The Developer Exception Page displays detailed information about unhandled request exceptions. The ASP.NET Core templates generate the following code:

:::code language=»csharp» source=»error-handling/samples/5.x/ErrorHandlingSample/Startup.cs» id=»snippet» highlight=»3-6″:::

The preceding highlighted code enables the developer exception page when the app is running in the Development environment.

The templates place xref:Microsoft.AspNetCore.Builder.DeveloperExceptionPageExtensions.UseDeveloperExceptionPage%2A early in the middleware pipeline so that it can catch unhandled exceptions thrown in middleware that follows.

The preceding code enables the Developer Exception Page only when the app runs in the Development environment. Detailed exception information shouldn’t be displayed publicly when the app runs in the Production environment. For more information on configuring environments, see xref:fundamentals/environments.

The Developer Exception Page can include the following information about the exception and the request:

  • Stack trace
  • Query string parameters if any
  • Cookies if any
  • Headers

The Developer Exception Page isn’t guaranteed to provide any information. Use Logging for complete error information.

Exception handler page

To configure a custom error handling page for the Production environment, call xref:Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions.UseExceptionHandler%2A. This exception handling middleware:

  • Catches and logs unhandled exceptions.
  • Re-executes the request in an alternate pipeline using the path indicated. The request isn’t re-executed if the response has started. The template-generated code re-executes the request using the /Error path.

[!WARNING]
If the alternate pipeline throws an exception of its own, Exception Handling Middleware rethrows the original exception.

In the following example, xref:Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions.UseExceptionHandler%2A adds the exception handling middleware in non-Development environments:

:::code language=»csharp» source=»error-handling/samples/5.x/ErrorHandlingSample/Startup.cs» id=»snippet_DevPageAndHandlerPage» highlight=»5-9″:::

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 for the Home controller.

The exception handling middleware re-executes the request using the original HTTP method. If an error handler endpoint is restricted to a specific set of HTTP methods, it runs only for those HTTP methods. For example, an MVC controller action that uses the [HttpGet] attribute runs only for GET requests. To ensure that all requests reach the custom error handling page, don’t restrict them to a specific set of HTTP methods.

To handle exceptions differently based on the original HTTP method:

  • For Razor Pages, create multiple handler methods. For example, use OnGet to handle GET exceptions and use OnPost to handle POST exceptions.
  • For MVC, apply HTTP verb attributes to multiple actions. For example, use [HttpGet] to handle GET exceptions and use [HttpPost] to handle POST exceptions.

To allow unauthenticated users to view the custom error handling page, ensure that it supports anonymous access.

Access the exception

Use xref:Microsoft.AspNetCore.Diagnostics.IExceptionHandlerPathFeature to access the exception and the original request path in an error handler. The following code adds ExceptionMessage to the default Pages/Error.cshtml.cs generated by the ASP.NET Core templates:

:::code language=»csharp» source=»error-handling/samples/5.x/ErrorHandlingSample/Pages/Error.cshtml.cs» id=»snippet»:::

[!WARNING]
Do not serve sensitive error information to clients. Serving errors is a security risk.

To test the exception in the sample app:

  • Set the environment to production.
  • Remove the comments from webBuilder.UseStartup<Startup>(); in Program.cs.
  • 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%2A. Using a lambda allows access to the error before returning the response.

The following code uses a lambda for exception handling:

:::code language=»csharp» source=»error-handling/samples/5.x/ErrorHandlingSample/StartupLambda.cs» id=»snippet»:::

[!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 test the exception handling lambda in the sample app:

  • Set the environment to production.
  • Remove the comments from webBuilder.UseStartup<StartupLambda>(); in Program.cs.
  • 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 error status codes, such as 404 — Not Found. When the app sets an HTTP 400-599 error status code that doesn’t have a body, it returns the status code and an empty response body. To provide status code pages, use the status code pages middleware. To enable default text-only handlers for common error status codes, call xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePages%2A in the Startup.Configure method:

:::code language=»csharp» source=»error-handling/samples/5.x/ErrorHandlingSample/StartupUseStatusCodePages.cs» id=»snippet» highlight=»13″:::

Call UseStatusCodePages before request handling middleware. For example, call UseStatusCodePages before the Static File Middleware and the Endpoints Middleware.

When UseStatusCodePages isn’t used, navigating to a URL without an endpoint returns a browser-dependent error message indicating the endpoint can’t be found. For example, navigating to Home/Privacy2. When UseStatusCodePages is called, the browser returns:

Status Code: 404; Not Found

UseStatusCodePages isn’t typically used in production because it returns a message that isn’t useful to users.

To test UseStatusCodePages in the sample app:

  • Set the environment to production.
  • Remove the comments from webBuilder.UseStartup<StartupUseStatusCodePages>(); in Program.cs.
  • Select the links on the home page on the home page.

[!NOTE]
The status code pages middleware does not catch exceptions. To provide a custom error handling page, use the exception handler page.

UseStatusCodePages with format string

To customize the response content type and text, use the overload of xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePages%2A that takes a content type and format string:

:::code language=»csharp» source=»error-handling/samples/5.x/ErrorHandlingSample/StartupFormat.cs» id=»snippet» highlight=»13-14″:::

In the preceding code, {0} is a placeholder for the error code.

UseStatusCodePages with a format string isn’t typically used in production because it returns a message that isn’t useful to users.

To test UseStatusCodePages in the sample app, remove the comments from webBuilder.UseStartup<StartupFormat>(); in Program.cs.

UseStatusCodePages with lambda

To specify custom error-handling and response-writing code, use the overload of xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePages%2A that takes a lambda expression:

:::code language=»csharp» source=»error-handling/samples/5.x/ErrorHandlingSample/StartupStatusLambda.cs» id=»snippet» highlight=»13-20″:::

UseStatusCodePages with a lambda isn’t typically used in production because it returns a message that isn’t useful to users.

To test UseStatusCodePages in the sample app, remove the comments from webBuilder.UseStartup<StartupStatusLambda>(); in Program.cs.

UseStatusCodePagesWithRedirects

The xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePagesWithRedirects%2A extension method:

  • Sends a 302 — Found status code to the client.
  • Redirects the client to the error handling endpoint provided in the URL template. The error handling endpoint typically displays error information and returns HTTP 200.

:::code language=»csharp» source=»error-handling/samples/5.x/ErrorHandlingSample/StartupSCredirect.cs» id=»snippet» highlight=»13″:::

The URL template can include a {0} placeholder for the status code, as shown in the preceding code. If the URL template starts with ~ (tilde), the ~ is replaced by the app’s PathBase. When specifying an endpoint in the app, create an MVC view or Razor page for the endpoint. For a Razor Pages example, see Pages/MyStatusCode.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.

To test UseStatusCodePages in the sample app, remove the comments from webBuilder.UseStartup<StartupSCredirect>(); in Program.cs.

UseStatusCodePagesWithReExecute

The xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePagesWithReExecute%2A extension method:

  • Returns the original status code to the client.
  • Generates the response body by re-executing the request pipeline using an alternate path.

:::code language=»csharp» source=»error-handling/samples/5.x/ErrorHandlingSample/StartupSCreX.cs» id=»snippet» highlight=»13″:::

If an endpoint within the app is specified, create an MVC view or Razor page for the endpoint. Ensure UseStatusCodePagesWithReExecute is placed before UseRouting so the request can be rerouted to the status page. For a Razor Pages example, see Pages/MyStatusCode2.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 /.

The endpoint that processes the error can get the original URL that generated the error, as shown in the following example:

:::code language=»csharp» source=»error-handling/samples/5.x/ErrorHandlingSample/Pages/MyStatusCode2.cshtml.cs» id=»snippet»:::

For a Razor Pages example, see Pages/MyStatusCode2.cshtml in the sample app.

To test UseStatusCodePages in the sample app, remove the comments from webBuilder.UseStartup<StartupSCreX>(); in Program.cs.

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:

:::code language=»csharp» source=»error-handling/samples/5.x/ErrorHandlingSample/Pages/Privacy.cshtml.cs» id=»snippet»:::

Exception-handling code

Code in exception handling pages can also throw exceptions. Production error pages should be tested thoroughly and take extra care to avoid throwing exceptions of their own.

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 an 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 the 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

The Database developer page exception filter AddDatabaseDeveloperPageExceptionFilter captures database-related exceptions that can be resolved by using Entity Framework Core migrations. When these exceptions occur, an HTML response is generated with details of possible actions to resolve the issue. This page is enabled only in the Development environment. The following code was generated by the ASP.NET Core Razor Pages templates when individual user accounts were specified:

:::code language=»csharp» source=»error-handling/samples/5.x/StartupDBexFilter.cs» id=»snippet» highlight=»6″:::

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 exceptions that occur during the execution of a controller action or another filter. For more information, see xref:mvc/controllers/filters#exception-filters.

Exception filters are useful for trapping exceptions that occur within MVC actions, but they’re not as flexible as the built-in exception handling middleware, UseExceptionHandler. We recommend using UseExceptionHandler, unless you need to perform error handling differently based on which MVC action is chosen.

:::code language=»csharp» source=»error-handling/samples/5.x/ErrorHandlingSample/Startup.cs» id=»snippet» highlight=»9″:::

Model state errors

For information about how to handle model state errors, see Model binding and Model validation.

Additional resources

  • xref:test/troubleshoot-azure-iis
  • xref:host-and-deploy/azure-iis-errors-reference

:::moniker-end

:::moniker range=»< aspnetcore-5.0″

By Tom Dykstra, 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.)

Developer Exception Page

The Developer Exception Page displays detailed information about request exceptions. The ASP.NET Core templates generate the following code:

:::code language=»csharp» source=»error-handling/samples/2.x/ErrorHandlingSample/Startup.cs» id=»snippet_DevPageAndHandlerPage» highlight=»1-4″:::

The preceding code enables the developer exception page when the app is running in the Development environment.

The templates place xref:Microsoft.AspNetCore.Builder.DeveloperExceptionPageExtensions.UseDeveloperExceptionPage%2A before any middleware so exceptions are caught in the middleware that follows.

The preceding code enables the Developer Exception Page only when the app is running in the Development environment. Detailed exception information should not be displayed publicly when the app runs in production. For more information on configuring environments, see xref:fundamentals/environments.

The Developer Exception Page includes the following information about the exception and the request:

  • Stack trace
  • Query string parameters if any
  • Cookies if any
  • Headers

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. The template generated code re-executes the request to /Error.

In the following example, xref:Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions.UseExceptionHandler%2A adds the Exception Handling Middleware in non-Development environments:

:::code language=»csharp» source=»error-handling/samples/2.x/ErrorHandlingSample/Startup.cs» id=»snippet_DevPageAndHandlerPage» highlight=»5-9″:::

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 in the Home controller.

Don’t mark 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 if unauthenticated users should see 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:

:::code language=»csharp» source=»error-handling/samples/2.x/ErrorHandlingSample/Pages/MyFolder/Error.cshtml.cs» id=»snippet_ExceptionHandlerPathFeature»:::

[!WARNING]
Do not serve sensitive error information to clients. Serving errors is a security risk.

To trigger the preceding exception handling page, set the environment to productions and force an exception.

Exception handler lambda

An alternative to a custom exception handler page is to provide a lambda to xref:Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions.UseExceptionHandler%2A. Using a lambda allows access to the error before returning the response.

Here’s an example of using a lambda for exception handling:

:::code language=»csharp» source=»error-handling/samples/2.x/ErrorHandlingSample/Startup.cs» id=»snippet_HandlerPageLambda»:::

In the preceding code, await context.Response.WriteAsync(new string(' ', 512)); is added so the Internet Explorer browser displays the error message rather than an IE error message. For more information, see this GitHub issue.

[!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.

To enable default text-only handlers for common error status codes, call xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePages%2A in the Startup.Configure method:

:::code language=»csharp» source=»error-handling/samples/2.x/ErrorHandlingSample/Startup.cs» id=»snippet_StatusCodePages»:::

Call UseStatusCodePages before request handling middleware (for example, Static File Middleware and MVC Middleware).

When UseStatusCodePages isn’t used, navigating to a URL without an endpoint returns a browser dependent error message indicating the endpoint can’t be found. For example, navigating to Home/Privacy2. When UseStatusCodePages is called, the browser returns:

Status Code: 404; Not Found

UseStatusCodePages with format string

To customize the response content type and text, use the overload of xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePages%2A that takes a content type and format string:

:::code language=»csharp» source=»error-handling/samples/2.x/ErrorHandlingSample/Startup.cs» id=»snippet_StatusCodePagesFormatString»:::

UseStatusCodePages with lambda

To specify custom error-handling and response-writing code, use the overload of xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePages%2A that takes a lambda expression:

:::code language=»csharp» source=»error-handling/samples/2.x/ErrorHandlingSample/Startup.cs» id=»snippet_StatusCodePagesLambda»:::

UseStatusCodePagesWithRedirects

The xref:Microsoft.AspNetCore.Builder.StatusCodePagesExtensions.UseStatusCodePagesWithRedirects%2A extension method:

  • Sends a 302 — Found status code to the client.
  • Redirects the client to the location provided in the URL template.

:::code language=»csharp» source=»error-handling/samples/2.x/ErrorHandlingSample/Startup.cs» id=»snippet_StatusCodePagesWithRedirect»:::

The URL template can include a {0} placeholder for the status code, as shown in the example. If the URL template starts with ~ (tilde), the ~ 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%2A extension method:

  • Returns the original status code to the client.
  • Generates the response body by re-executing the request pipeline using an alternate path.

:::code language=»csharp» source=»error-handling/samples/2.x/ErrorHandlingSample/Startup.cs» id=»snippet_StatusCodePagesWithReExecute»:::

If you point to an endpoint within the app, create an MVC view or Razor page for the endpoint. Ensure UseStatusCodePagesWithReExecute is placed before UseRouting so the request can be rerouted to the status page. 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:

The endpoint that processes the error can get the original URL that generated the error, as shown in the following example:

:::code language=»csharp» source=»error-handling/samples/2.x/ErrorHandlingSample/Pages/StatusCode.cshtml.cs» id=»snippet_StatusCodeReExecute»:::

Don’t mark 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 if unauthenticated users should see the error view.

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

xref:Microsoft.AspNetCore.Builder.DatabaseErrorPageExtensions.UseDatabaseErrorPage%2A requires the Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore NuGet package.

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.

Additional resources

  • xref:test/troubleshoot-azure-iis
  • xref:host-and-deploy/azure-iis-errors-reference

:::moniker-end

Обработка ошибок

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7

Последнее обновление: 06.11.2019

Ошибки в приложении можно условно разделить на два типа: исключения, которые возникают в процессе выполнения кода (например, деление на 0), и
стандартные ошибки протокола HTTP (например, ошибка 404).

Обычные исключения могут быть полезны для разработчика в процессе создания приложения, но простые пользователи не должны будут их видеть.

UseDeveloperExceptionPage

Если мы создаем проект ASP.NET Core, например, по типу Empty (да и в других типах проектов), то в классе Startup мы можем найти в начале метода Configure() следующие строки:

if (env.IsDevelopment())
{
	app.UseDeveloperExceptionPage();
}

Если приложение находится в состоянии разработки, то с помощью middleware app.UseDeveloperExceptionPage() приложение перехватывает исключения и
выводит информацию о них разработчику.

Например, изменим класс Startup следующим образом:

public class Startup
{
	public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
	{
		if (env.IsDevelopment())
		{
			app.UseDeveloperExceptionPage();
		}
		app.Run(async (context) =>
		{
			int x = 0;
			int y = 8 / x;
			await context.Response.WriteAsync($"Result = {y}");
		});
	}
}

В middleware app.Run симулируется генерация исключения при делении ноль. И если мы запустим проект, то в браузере мы увидим
информацию об исключении:

Обработка исключений в ASP.NET Core

Этой информации достаточно, чтобы определить где именно в коде произошло исключение.

Теперь посмотрим, как все это будет выглядеть для простого пользователя. Для этого изменим метод Configure:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
	env.EnvironmentName = "Production";
	if (env.IsDevelopment())
	{
		app.UseDeveloperExceptionPage();
	}
	app.Run(async (context) =>
	{
		int x = 0;
		int y = 8 / x;
		await context.Response.WriteAsync($"Result = {y}");
	});
}

Выражение env.EnvironmentName = "Production"; устанавливает режим развертывания вместо режима разработки. В этом случае выражение if (env.IsDevelopment()) будет возвращать false, и мы увидим в браузере что-то наподобие «HTTP ERROR 500»

HTTP ERROR 500 в ASP.NET Core

UseExceptionHandler

Это не самая лучшая ситуация, и нередко все-таки возникает необходимость дать пользователям некоторую информацию о том, что же все-таки произошло. Либо потребуется как-то обработать данную ситуацию.
Для этих целей можно использовать еще один встроенный middleware в виде метода UseExceptionHandler(). Он перенаправляет
при возникновении исключения на некоторый адрес и позволяет обработать исключение. Например, изменим метод Configure следующим образом:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
	env.EnvironmentName = "Production";
	
	if (env.IsDevelopment())
	{
		app.UseDeveloperExceptionPage();
	}
	else
	{
		app.UseExceptionHandler("/error");
	}
	
	app.Map("/error", ap => ap.Run(async context =>
	{
		await context.Response.WriteAsync("DivideByZeroException occured!");
	}));
	
	app.Run(async (context) =>
	{
		int x = 0;
		int y = 8 / x;
		await context.Response.WriteAsync($"Result = {y}");
	});
}

Метод app.UseExceptionHandler("/error"); перенаправляет при возникновении ошибки на адрес «/error».

Для обработки пути по определенному адресу здесь использовался метод app.Map(). В итоге при возникновении исключения будет срабатывать делегат
из метода app.Map.

Error Handling in ASP.NET Core

Следует учитывать, что оба middleware — app.UseDeveloperExceptionPage() и app.UseExceptionHandler()
следует помещать ближе к началу конвейера middleware.

Обработка ошибок HTTP

В отличие от исключений стандартный функционал проекта ASP.NET Core почти никак не обрабатывает ошибки HTTP, например, в случае если ресурс не найден.
При обращении к несуществующему ресурсу мы увидим в браузере пустую страницу, и только через консоль веб-браузера мы сможем увидеть статусный код.
Но с помощью компонента StatusCodePagesMiddleware можно добавить в проект отправку информации о статусном коде.
Для этого добавим в метод Configure() класса Startup вызов app.UseStatusCodePages():

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
	if (env.IsDevelopment())
	{
		app.UseDeveloperExceptionPage();
	}
	
	// обработка ошибок HTTP
	app.UseStatusCodePages();
	
	app.Map("/hello", ap => ap.Run(async (context) =>
	{
		await context.Response.WriteAsync($"Hello ASP.NET Core");
	}));
}

Здесь мы можем обращаться только по адресу «/hello». При обращении ко всем остальным адресам браузер отобразит базовую информацию об ошибке:

UseStatusCodePages в ASP.NET Core

Данный метод позволяет настроить отправляемое пользователю сообщение. В частности, мы можем изменить вызов метода так:

app.UseStatusCodePages("text/plain", "Error. Status code : {0}");

В качестве первого параметра указывается MIME-тип ответа, а в качестве второго — собственно то сообщение, которое увидит пользователь. В сообщение мы можем
передать код ошибки через плейсхолдер «{0}».

Вместо метода app.UseStatusCodePages() мы также можем использовать еще пару других, которые также обрабатываю ошибки HTTP.

С помощью метода app.UseStatusCodePagesWithRedirects() можно выполнить переадресацию на определенный метод, который непосредственно обработает статусный код:

app.UseStatusCodePagesWithRedirects("/error?code={0}");

Здесь будет идти перенаправление по адресу «/error?code={0}». В качестве параметра через плейсхолдер «{0}» будет передаваться статусный код
ошибки.

Но теперь при обращении к несуществующему ресурсу клиент получит статусный код 302 / Found. То есть формально несуществующий ресурс будет существовать, просто статусный код 302
будет указывать, что ресурс перемещен на другое место — по пути «/error/404».

Подобное поведение может быть неудобно, особенно с точки зрения поисковой индексации, и в этом случае мы можем применить другой метод
app.UseStatusCodePagesWithReExecute():

app.UseStatusCodePagesWithReExecute("/error", "?code={0}");

Первый параметр метода указывает на путь перенаправления, а второй задает параметры строки запроса, которые будут передаваться при перенаправлении.
Вместо плейсхолдера {0} опять же будет передаваться статусный код ошибки. Формально мы получим тот же ответ, так как так же будет идти перенаправление на путь «/error?code=404». Но теперь браузер получит оригинальный статусный код 404.

Пример использования:

public void Configure(IApplicationBuilder app)
{
	// обработка ошибок HTTP
	app.UseStatusCodePagesWithReExecute("/error", "?code={0}");

	app.Map("/error", ap => ap.Run(async context =>
	{
		await context.Response.WriteAsync($"Err: {context.Request.Query["code"]}");
	}));

	app.Map("/hello", ap => ap.Run(async (context) =>
	{
		await context.Response.WriteAsync($"Hello ASP.NET Core");
	}));
}

Настройка обработки ошибок в web.config

Еще один способ обработки кодов ошибок представляет собой определение и настройка в файле конфигурации web.config элемента
httpErrors. Этот способ в принципе использовался и в других версиях ASP.NET.
В ASP.NET Core он также доступен, однако имеет очень ограниченное действие. В частности, мы его можем использовать только при развертывании на IIS, а также не можем использовать ряд настроек.

Итак, добавим в корень проекта новый элемент Web Configurarion File, который естественно назовем web.config:

Обработка ошибок в web.config

Изменим его следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<configuration>

  <system.webServer>
	<httpErrors errorMode="Custom" existingResponse="Replace">
      <remove statusCode="404"/>
	  <remove statusCode="403"/>
      <error statusCode="404" path="404.html" responseMode="File"/>
      <error statusCode="403" path="403.html" responseMode="File"/>
	</httpErrors>
   
    <handlers>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/>
    </handlers>
    <aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".logsstdout" forwardWindowsAuthToken="false"/>
  </system.webServer>
</configuration>

Также для обработки ошибок добавим в корень проекта новый файл 404.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Ошибка 404</title>
</head>
<body>
    <h1>Ошибка 404</h1>
    <h2>Ресурс не найден!</h2>
</body>
</html>

По аналогии можно добавить файл 403.html для ошибки 403.

Итак, элемент httpErrors имеет ряд настроек. Для тестирования настроек локально, необходимо установить атрибут errorMode="Custom".
Если тестирование необязательно, и приложение уже развернуто для использования, то можно установить значение errorMode="DetailedLocalOnly".

Значение existingResponse="Replace" позволит отобразить ошибку по оригинальному запрошенному пути без переадресации.

Внутри элемента httpErrors с помощью отдельных элементов error устанавливается обработка ошибок. Атрибут statusCode
задает статусный код, атрибут path — адрес url, который будет вызываться, а атрибут responseMode указывает, как будет обрабатываться ответ вызванному url.
Атрибут responseMode имеет значение File, что позволяет рассматривать адрес url из атрибута path как статическую страницу и использовать ее в качестве ответа

Настройки элемента httpErrors могут наследоваться с других уровней, например, от файла конфигурации machine.config. И чтобы удалить
все унаследованные настройки, применяется элемент <clear />. Чтобы удалить настройки для отдельных ошибок, применяется элемент
<remove />.

Для тестирования используем следующий класс Startup:

public class Startup
{
	public void Configure(IApplicationBuilder app)
	{
		app.Map("/hello", ap => ap.Run(async (context) =>
		{
			await context.Response.WriteAsync($"Hello ASP.NET Core");
		}));
	}
}

И после обращения к несуществующему ресурсу в приложении отобразится содержимое из файла 404.html.

Настройка обработки ошибок в web.config в ASP.NET Core

Handling 404 Not Found in Asp.Net Core

You might be surprised to find that the default asp.net core mvc templates do not handle 404 errors gracefully resulting in the standard browser error screen when a page is not found. This posts looks at the various methods for handling 404 not found errors in asp.net core.

The Problem

Without additional configuration, this is what a (chrome) user will see if they visit a URL that does not exist:

Chrome Default 404 Screen

Fortunately, it is very simple to handle error status codes. We’ll cover three techniques below.

The Solution

In previous versions of Asp.Net MVC, the primary place for handling 404 errors was in the web.config.

You probably remember the <customErrors> section which handled 404’s from the ASP.NET pipeline as well as <httpErrors> which was lower level and handled IIS 404’s. It was all a little confusing.

In .Net core, things are different and there is no need to play around with XML config (though you can still use httpErrors in web.config if you are proxying via IIS and you really want to :-)).

There are really two different situations that we need to handle when dealing with not-found errors.

There is the case where the URL doesn’t match any route. In this situation, if we cannot ascertain what the user was looking for, we need to return a generic not found page. There are two common techniques for handling this but first we’ll talk about the second situation. This is where the URL matches a route but one or more parameter is invalid. We can address this with a custom view.

Custom Views

An example for this case would be a product page with an invalid or expired id. Here, we know the user was looking for a product and instead of returning a generic error, we can be a bit more helpful and return a custom not found page for products. This still needs to return a 404 status code but we can make the page less generic, perhaps pointing the user at similar or popular products.

Handling these cases is trivial. All we need to do is set the status code before returning our custom view:

public async Task<IActionResult> GetProduct(int id)
{
    var viewModel = await _db.Get<Product,GetProductViewModel>(id);

    if (viewModel == null)
    {
        Response.StatusCode = 404;
        return View("ProductNotFound");
    }

    return View(viewModel);
}

Of course, you might prefer to wrap this up into a custom action result:

public class NotFoundViewResult : ViewResult
{
    public NotFoundViewResult(string viewName)
    {
        ViewName = viewName;
        StatusCode = (int)HttpStatusCode.NotFound;
    }
}

This simplifies our action slightly:

public async Task<IActionResult> GetProduct(int id)
{
    var viewModel = await _db.Get<Product,GetProductViewModel>(id);

    if (viewModel == null)
    {
        return new NotFoundViewResult("ProductNotFound");
    }

    return View(viewModel);
}

This easy technique covers specific 404 pages. Let’s now look at generic 404 errors where we cannot work out what the user was intending to view.

Catch-all route

Creating a catch-all route was possible in previous version of MVC and in .Net Core it works in exactly the same way. The idea is that you have a wildcard route that will pick up any URL that has not been handled by any other route. Using attribute routing, this is written as:

[Route("{*url}", Order = 999)]
public IActionResult CatchAll()
{
    Response.StatusCode = 404;
    return View();
}

It is important to specify the Order to ensure that the other routes take priority.

A catch-all route works reasonably well but it is not the preferred option in .Net Core. While a catch-all route will handle 404’s, the next technique will handle any non-success status code so you can do the following (probably in an actionfilter in production):

public async Task<IActionResult> GetProduct(int id)
{
    ...

    if (RequiresThrottling())
    {
        return new StatusCodeResult(429)
    }

    if (!HasPermission(id))
    {
        return Forbid();
    }

    ...
}

Status Code Pages With Re Execute

StatusCodePagesWithReExecute is a clever piece of Middleware that handles non-success status codes where the response has not already started. This means that if you use the custom view technique detailed above then the 404 status code will not be handled by the middleware (which is exactly what we want).

When an error code such as a 404 is returned from an inner middleware component, StatusCodePagesWithReExecute allows you to execute a second controller action to handle the status code.

You add it to the pipeline with a single command in startup.cs:

app.UseStatusCodePagesWithReExecute("/error/{0}");
...
app.UseMvc();

The order of middleware definition is important and you need to ensure that StatusCodeWithReExecute is registered before any middleware that could return an error code (such as the MVC middleware).

You can specify a fixed path to execute or use a placeholder for the status code value as we have done above.

You can also point to both static pages (assuming that you have the StaticFiles middleware in place) and controller actions.

In this example, we have a separate action for 404. Any other non-success status code hits, the Error action.

[Route("error/404")]
public IActionResult Error404()
{
    return View();
}

[Route("error/{code:int}")]
public IActionResult Error(int code)
{
    // handle different codes or just return the default error view
    return View();
}

Obviously, you can tailor this to your needs. For example, if you are using request throttling as we showed in the previous section then you can return a 429 specific page explaining why the request failed.

Conclusion

Handling specific cases of page not found is best addressed with a custom view and setting the status code (either directly or via a custom action result).

Handling more generic 404 errors (or in fact any non-success status code) can be achieved very easily by using the StatusCodeWithReExecute middleware. Together, these two techniques are the preferred methods for handling non-success HTTP status codes in Asp.Net Core.

By adding StatusCodeWithReExecute to the pipeline as we have done above, it will run for all requests but this may not be what we want all of the time. In the next post we will look at how to handle projects containing both MVC and API actions where we want to respond differently to 404’s for each type.

Useful or Interesting?

If you liked the article, I would really appreciate it if you could share it with your Twitter followers.

Share
on Twitter

Comments

Joydip Kanjilal

By ,

Contributor,

InfoWorld

|

Take advantage of ASP.NET Core middleware to handle 404 errors more gracefully in ASP.NET Core MVC

How to handle 404 errors in ASP.NET Core MVC

Thinkstock

ASP.NET Core MVC is the .NET Core counterpart of the ASP.NET MVC framework for building cross-platform, scalable, high-performance web applications and APIs using the Model-View-Controller design pattern. Surprisingly, although ASP.NET Core provides plenty of options for handling 404 errors gracefully, the ASP.NET Core MVC runtime doesn’t take advantage of them by default.

As a result, when a web page is not found and a 404 error is returned by the application, ASP.NET Core MVC presents only a generic browser error page (as shown in Figure 1 below). This article discusses three options in ASP.NET Core we can use to handle 404 errors more gracefully.

To work with the code examples provided in this article, you should have Visual Studio 2019 installed in your system. If you don’t already have a copy, you can download Visual Studio 2019 here.

Create an ASP.NET Core MVC project

First off, let’s create an ASP.NET Core project in Visual Studio. Assuming Visual Studio 2019 is installed in your system, follow the steps outlined below to create a new ASP.NET Core project in Visual Studio.

  1. Launch the Visual Studio IDE.
  2. Click on “Create new project.”
  3. In the “Create new project” window, select “ASP.NET Core Web Application” from the list of templates displayed.
  4. Click Next. 
  5. In the “Configure your new project” window shown next, specify the name and location for the new project.
  6. Click Create.
  7. In the “Create a New ASP.NET Core Web Application” window, select .NET Core as the runtime and ASP.NET Core 3.1 (or later) from the drop-down list at the top.
  8. Select “Web Application (Model-View-Controller)” as the project template to create a new ASP.NET Core MVC application.
  9. Ensure that the check boxes “Enable Docker Support” and “Configure for HTTPS” are unchecked as we won’t be using those features here.
  10. Ensure that Authentication is set to “No Authentication” as we won’t be using authentication either.
  11. Click Create.

Following these steps will create a new ASP.NET Core MVC project in Visual Studio 2019. We’ll use this project to illustrate our 404 error handling options in the subsequent sections of this article.

When you execute the ASP.NET Core MVC project we’ve created in the preceding section, you will see the home page of the application together with the welcome message as shown in Figure 1 below. 

aspnet core mvc 404 errors 01 IDG

Figure 1: The default home page in ASP.NET Core MVC. 

Now let’s try to browse a web page that doesn’t exist. To do this, type http://localhost:6440/welcome in the address bar of your browser while the application is in execution. When the ASP.NET Core MVC engine fails to locate the resource for the specified URL, a 404 error will be returned and you will be presented with the following error page. That’s not very elegant, is it?

aspnet core mvc 404 errors 02 IDG

Figure 2: The default 404 error page displayed by ASP.NET Core MVC for a non-existent web page.

Check Response.StatusCode in ASP.NET Core MVC

There are several ways in which you can improve on this generic error page. A simple solution is to check for the HTTP status code 404 in the response. If found, you can redirect the control to a page that exists. The following code snippet illustrates how you can write the necessary code in the Configure method of the Startup class to redirect to the home page if a 404 error has occurred.

 app.Use(async (context, next) =>
    {
        await next();
        if (context.Response.StatusCode == 404)
        {
            context.Request.Path = "/Home";
            await next();
        }
    });

Now if you execute the application and try to browse the URL http://localhost:6440/welcome, you will be redirected to the home page of the application.

The complete code of the Configure method is given below for your reference.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }
            app.Use(async (context, next) =>
            {
                await next();
                if (context.Response.StatusCode == 404)
                {
                    context.Request.Path = "/Home";
                    await next();
                }
            });
            app.UseStaticFiles();
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }

Use UseStatusCodePages middleware in ASP.NET Core MVC

A second solution for handling 404 errors in ASP.NET Core is by using the built-in UseStatusCodePages middleware. The following code snippet shows how you can implement StatusCodePages in the Configure method of the Startup class.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseStatusCodePages();
            //Other code
        }

Now when you execute the application and browse to the non-existent resource, the output will be similar to Figure 3.

aspnet core mvc 404 errors 03 IDG

Figure 3: The ASP.NET Core StatusCodePages middleware in action. 

Use UseStatusCodePagesWithReExecute middleware in ASP.NET Core MVC

You can take advantage of the UseStatusCodePagesWithReExecute middleware to handle non-success status codes in cases where the process of generating the response has not been started. Hence this middleware will not handle HTTP 404 status code errors — rather, when a 404 error occurs the control will be passed to another controller action to handle the error.

The following code snippet illustrates how you can use this middleware to redirect to another action method.

app.UseStatusCodePagesWithReExecute("/Home/HandleError/{0}");

Here’s what the action method would look like.

[Route("/Home/HandleError/{code:int}")]
public IActionResult HandleError(int code)
{
   ViewData["ErrorMessage"] = $"Error occurred. The ErrorCode is: {code}";
   return View("~/Views/Shared/HandleError.cshtml");
}

I leave it to you to create the HandleError view to display the error message.

Finally, you might want to create views specifically for an error code. For example, you might create views such as Home/Error/500.cshtml or Home/Error/404.cshtml. You could then check the HTTP error code and redirect to the appropriate error page.

Yet another way of handling page not found errors is by using a custom view and setting the error code appropriately. When an error occurs in your application, you could redirect the user to the appropriate error page and display your custom error message describing the error.

How to do more in ASP.NET Core:

  • How to use dependency injection in action filters in ASP.NET Core 3.1
  • How to use the options pattern in ASP.NET Core
  • How to use endpoint routing in ASP.NET Core 3.0 MVC
  • How to export data to Excel in ASP.NET Core 3.0
  • How to use LoggerMessage in ASP.NET Core 3.0
  • How to send emails in ASP.NET Core
  • How to log data to SQL Server in ASP.NET Core
  • How to schedule jobs using Quartz.NET in ASP.NET Core
  • How to return data from ASP.NET Core Web API
  • How to format response data in ASP.NET Core
  • How to consume an ASP.NET Core Web API using RestSharp
  • How to perform async operations using Dapper
  • How to use feature flags in ASP.NET Core
  • How to use the FromServices attribute in ASP.NET Core
  • How to work with cookies in ASP.NET Core
  • How to work with static files in ASP.NET Core
  • How to use URL Rewriting Middleware in ASP.NET Core
  • How to implement rate limiting in ASP.NET Core
  • How to use Azure Application Insights in ASP.NET Core
  • Using advanced NLog features in ASP.NET Core
  • How to handle errors in ASP.NET Web API
  • How to implement global exception handling in ASP.NET Core MVC
  • How to handle null values in ASP.NET Core MVC
  • Advanced versioning in ASP.NET Core Web API
  • How to work with worker services in ASP.NET Core
  • How to use the Data Protection API in ASP.NET Core
  • How to use conditional middleware in ASP.NET Core
  • How to work with session state in ASP.NET Core
  • How to write efficient controllers in ASP.NET Core

Joydip Kanjilal is a Microsoft MVP in ASP.NET, as well as a speaker and author of several books and articles. He has more than 20 years of experience in IT including more than 16 years in Microsoft .NET and related technologies.

Copyright © 2020 IDG Communications, Inc.

Возможно, вам также будет интересно:

  • Asko ошибка f10 посудомойка
  • Asko вытяжка ошибка f6
  • Asko f11 ошибка на стиральной машине
  • Asko d3142 ошибка f2
  • Ashen не запускается ошибка

  • Понравилась статья? Поделить с друзьями:
    0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии