Global Exception Handling on ASP.NET Core Applications

This is a cross-posting of ASP.NET Core Tips & Tricks – Global Exception Handling at Kloud.

Exception handling is one of most important but irritating jobs for developers. There are tons of articles about the importance of exception handling. Fortunately, ASP.NET Core application has got a lot of improvement for exception handling through the request/response pipeline. In this article, we’re going to have a brief look how we can handle exceptions.

Sample application can be found here:

Global Exception Filter - OWIN Pipeline

Unlike ASP.NET MVC applications, ASP.NET Core applications only use OWIN pipelines to handle requests and responses. In order to handle exceptions, UseExceptionHandler() middleware extension is provided out of the box. Therefore, it can be easily implemented like this:

However, if you want to do more control, creating a custom exception filter class would be recommended. The following code is a simple GlobalExceptionFilter class:

Microsoft.AspNet.Mvc package provides an interface called IExceptionFilter. It declares the OnException() method so the GlobalExceptionHandler implements it. As this class accepts the ILoggerFactory instance as its constructor parameter, we can write logs when an exception is thrown. It is implemented with log4Net, NLog and ApplicationInsights libraries. You can choose anything in your taste.

So, the GlobalExceptionFilter class can be resolved within the ConfigureServices() method on Startup.cs like:

Then, raise an exception within a controller and you will be able to see the error log like this:

Exception Handling outside OWIN Pipeline

As stated above, the GlobalExceptionFilter only works within the OWIN pipeline. How about handling outside OWIN pipeline? There are only three places to handle exceptions outside OWIN pipeline – Startup() constructor, ConfigureServices() method and Configure() method. Let’s have a look at the code below:

This is how the Configure() method handles exceptions. Note that this is the only place where we can handle exceptions. In other words, the other two places, Startup() and ConfigureServices() can throw exceptions but can’t handle them. It is because of the IApplicationBuilder.Run() method. This method takes HttpContext instance to handle exceptions. Hence, using try...catch block writes response messages to browsers.

One question still remains. How can the other two places handle exceptions? Here’s a trick for them:

All codes should be surrounded by try...catch block. If any exception is thrown, the _exceptions field having type of Dictionary<string, List<Exception>> stores the exception. If any exception is thrown from Startup() or ConfigureServices(), this is handled within the Configure() method like above.

Now, we can handle all exceptions inside/outside OWIN pipeline. As this is just an example, if you apply this approach into your production code, you need to carefully review and do a bit of refactoring.