Last update:

Error handling in ASP.NET Core applications

ASP.NET Core has several built-in features from the error handling department. We have access to few different middlewares and MVC filters. Here’s how they work and when to use which.

First of all, it’s important to distinguish between utilities that detect an erroneous status code and modify the response from those that actually handle exceptions. The former is represented by the StatusCodePagesMiddleware. The rest from the list below falls into the second category.

StatusCodePagesMiddleware

Comes in three variants and most commonly used via an extension method on IApplicationBuilder:

  • UseStatusCodePages() by default just returns a simple text message describing the HTTP status. It has overloads that allow customization of this message or even execution of entire new middleware chain (we have access to an IApplicationBuilder instance there)
  • UseStatusCodePagesWithReExecute(), as the name suggests, will re-execute the request as it had been received with another path. It assumes that there is a middleware or MVC action later in the pipeline that will handle such a request. Note that this re-execution happens only on the server. The client does not have any clue about this (i.e. nothing is returned to the client before the request is re-executed). If you need to know what was the original request path, Andrew Lock can help you.
  • UseStatusCodePagesWithRedirects() re-executes the request pipeline as well, but contrary to UseStatusCodePagesWithReExecute(), the client initiates this second execution. First, a redirect status code is sent with the response, then the client requests another page. This approach is less recommended than the previous one as the HTTP status codes won’t indicate any errors (so, you may end up with Google indexing your error pages, for example).

Note that this middleware will not catch any exceptions in your pipeline. So the code below won’t work as desired:

In the example above the exception will not be handled by the application at all, so user will not see the message we prepared.

The following will work just fine:

But when an exception happens we need a way to generate an error code based on it. For this, we can use ExceptionHandlerMiddleware described below.

DeveloperExceptionPageMiddleware

This one is for development only (unless you intend to expose your source code and exception details to the world). It catches any unhandled exception and renders a pretty error page with the line of code that threw, stack trace and few more details about the request.

ExceptionHandlerMiddleware

This can be thought of as a global try-catch block. It can catch exceptions and either re-execute the request using another path or run a custom pipeline.

The ExceptionHandlerMiddleware plays nicely with the StatusCodePagesMiddleware:

Just remember to put UseStatusCodePages and UseExceptionHandler as close to the top of the Configure method as possible. Any code that’s above won’t be protected by this middleware.

MVC Exception Filters

Having all the above error handling middleware, there should be no need for something else. Yet MVC has its own means of handling errors in action methods – exception filters. It’s still perfectly valid (and even recommended) to use error handling middleware with MVC but when you need to have access to MVC context, exception filters would be the way to go.

There are two interfaces we can implement to create our own filter: IExceptionFilter and IAsyncExceptionFilter. But in reality, instead of writing these classes from scratch, we can just subclass ExceptionFilterAttribute and override its OnException or OnExceptionAsync methods.

 

Wrapping up

In real life projects I often use a combination of all the middlewares I described. Very seldom I need to write my own MVC exception filter. Here’s my usual setup:

 

Further reading

2 comments

  1. Should UseStatusCodePages middleware always be called before the UseExceptionHandler?

    John on 9 October 2018, 18:27 UTC Reply
    1. I wouldn’t say always, as I can’t imagine all the possible use cases, but it makes sense to do so. UseExceptionHandler catches any unhandled exceptions and sets a status code, then UseStatusCodePages can prepare a response based on the status code.

      Michał Dudak on 9 October 2018, 21:06 UTC Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Michał Dudak