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: 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:
https://gist.github.com/justinyoo/6955a665cc6fcaa4f6c6
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:
https://gist.github.com/justinyoo/4c3526deee32f9358557
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:
https://gist.github.com/justinyoo/9e98ecbe651733a18aa9
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:
https://gist.github.com/justinyoo/269f45544ee710417353
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:
https://gist.github.com/justinyoo/df11d6f4aa5e1753c30e
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.