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: https://github.com/devkimchi/ASP.NET-Core-Tips-and-Tricks-Sample
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
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
ApplicationInsights libraries. You can choose anything in your taste.
GlobalExceptionFilter class can be resolved within the
ConfigureServices() method on
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 –
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,
ConfigureServices() can throw exceptions but can’t handle them. It is because of the
IApplicationBuilder.Run() method. This method takes
HttpContext instance to write responses. Hence, using
try...catch block catches any exception and writes response messages back 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
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.