ASP.NET Core MVC and Exception Handling
Simplifying the exception handling of ASP.NET Core MVC applications by using the NuGet SimpleExceptionHandling
Nowadays, when someone talks about web development in the .NET world, it is almost certain to be talking about ASP.NET MVC, ASP.NET Web API or, the more recently released, ASP.NET Core MVC. These are frameworks developed by Microsoft to help the development of server side logic for web applications.
In this article I’ll explain how can someone simplify the global handling of exceptions based on their type or properties by using a small library named Simple Exception Handling in ASP.NET Core MVC applications.
Exception handling in ASP.NET Core MVC
Exceptions, despite being rare, are an important aspect that any developer should be aware when creating applications in the .NET world. They can be handled inside try-catch-finally blocks but, most of the time, no particular handling logic need to be implemented or are completely unexpected, like the well known OutOfMemoryException, and will be managed by the global exception handler logic.
Global exception handlers are great to make sure all exceptions are handled by the server, even if the handling is just a log entry yet, despite being extremely helpful, they have some limitations regarding handling by exception type or properties.
Because global exception handlers are made to handle any type of exception, the developer receives a generic Exception instance. This is enough for most cases but, just like the try-catch-finally block, sometimes specific code by exception type and properties may be needed. This requirement can be easily achieved using the as keyword and checking if the result is not null. The problem with this approach is that code can become complicated and hard to understand if a bigger range of types are expected.
Lets imagine a simple REST API that has de following requirements by exception type:
- ValidationException — custom exception that indicates some entity received is not valid (missing required fields, invalid email format, etc). The server should return 422 Unprocessable Entity and log the exception as a warning;
- NotImplementedException — the server should return the status 501 Not Implemented and log the exception as critical because, lets say, someone forgot to do his job;
- TimeoutException — the server should return the status 504 Gateway Timeout and log the exception as error;
- Exception — if no match, the server should return a generic 500 Internal Server Error and log the exception as error;
In all cases, because this is an API, a JSON object will be returned with a more detailed message and error code about what happened.
So, to meet this criteria, in ASP.NET Core MVC using an IExceptionFilter the code would look something like this:
This type of code can be hard to understand because there are a lot of conditional code and, the more the exception, the more complicated it will get. Because we can’t use a try-catch-finally block, this code can become very hard to read.
The solution to make it more manageable and readable is to use a NuGet library like Simple Exception Handling.
Simple Exception Handling
This is a library I made myself to simplify the global exception handling of any type of applications when there is a need to execute some logic depending of exception type. The companies I have worked in are currently using it successfully in production environments, from ASP.NET (Core, Web API, MVC), WPF, WCF and Xamarin applications.
This library can be installed via NuGet using the following command:
It is compatible with almost every version of .NET framework (2.0 and up) with an MIT licence.
Using Simple Exception Handling
The example I gave above can be simplified and become more readable using this small library. It would look something like this:
As you can see, the code is more legible and concise, almost looking as a try-catch-finally block. The are some options, like passing arguments in the catch method, making the functions pure, having a finally action, optional handling, and so on.
I recommend giving it a good try the next time you have a requirement like this. Any questions you can send me a message or open an issue in the GitHub repository page.