Let’s get started
- It is common to see that popular HTTP error status codes such as
400 Bad Request
,401 Unauthorized
,
,404 Not found
, and so on return different HTTP Response formats. In fact, even for a single status code, the response could be plain text or JSON. This makes the error parsing at the client-side is very difficult since the response could vary based on the status code and sometimes even for the same status code.500 Internal Server Error
- In addition to this, the error handling logic is scattered across all the Controllers. That makes it tricky to change a response object since we would need to update every controller.
Below pseudo-code is an example controller with the inconsistent response for different error codes.
Consistent Error Handling
Taking a leaf out of JSON:API specification and JsonApiDotNetCore, I tried to implement a consistent way of handling errors in ASP.NET Core.
CREATE EXCEPTION CLASS
To solve the next part of our problem, we start by creating an Exception
classes for every error status code.
As you can see in the above code, we have a separate exception class for every error status code that we expect our application to return.
THROWING RELEVANT EXCEPTIONS FROM CODE
Next, instead of returning HTTP error status code from the Controller
, we throw a relevant exception.
If you are following Clean Architecture or Domain-Driven Design (DDD) in your project, then the Controllers are usually thin. With DDD, the business logic stays within the Domain. QueryHandler
and CommandHandler
act as an interface between the Controller
and Domain
/ Repository
. In addition to this, the cross-cutting concerns such a validation, authorization etc., are handled through Middeware
or ActionFilter
, keeping the Controllers lean.
This allows us to throw a relevant exception from different parts of our code. The below pseudo-code demonstrates how we can keep the error handling outside the Controllers by throwing the Exceptions.
Accordingly, we can return our custom errors from any layer of our application.
CREATE APPLICATION EXCEPTION MIDDLEWARE AND EXCEPTION HANDLER
Next, we create ApplicationExceptionMiddleware
and ExceptionHandler
classes to handle all the exceptions that are thrown from the different parts of the code. The ExceptionHandler
is one single place where we handle all our HTTP error status, and we return the error response to the client through ApplicationExceptionMiddleware.
Last but not the least, we need to register ExceptionHandler
and ApplicationExceptionMiddleware
in Startup.
Wrapping Up
In this post, I have presented a clean way to achieve consistent exception handling for your ASP.NET Core Rest APIs. I hope you enjoy reading this post and it was helpful in some way.
Happy Learning :)