ASP.NET Core Exception Middleware

Georgi Kamacharov
4 min readFeb 2, 2021

Microsoft documentation defines ASP.NET Core middleware as “software that’s assembled into an app pipeline to handle requests and responses”. The way I like to think about it — it’s a piece of logic that executes on every request.

middleware diagram

Introduction

In this specific story, we will look at how to setup an Exception middleware in your ASP.NET Web API. The end goal is to have one place to catch all your Exceptions and write the API response back.

The reason why this is very powerful is because you define a single place to handle all of your Exception logic and you only have one snippet of try {} catch {} code.

Exceptions and responses

Let’s take a look at how we can define custom Exceptions and a custom response for the middleware. You, of course, don’t have to do this part and can skip to the Middleware section.

Exceptions

I like using at least 2 different Exception classes. One is an abstract one that essentially defines the schema and the other is a friendly one that I can throw anywhere in the code — additionally, I have one for NotFound (404), but that is out of scope for this story.

AuthException.cs
AuthFriendlyException.cs

Responses

I define a specific class to return in the middleware response. This is helpful as it lets you customize the StatusCode and Message. This is based on ASP.NET’s built in ProblemDetails object.

As you might’ve already guessed — the StatusCode in the Exception maps to the Code in the AuthProblemDetail response object and — the Message in the Exception maps to the Message in the AuthProblemDetail response object.

Middleware

Now let’s take a look at creating the actual middleware. This specific one will consist of 2 main parts — delegate call and a function to write the response.

AuthExceptionMiddleware

As you can see, the try {} catch {} code is wrapped around the await _next(httpContext) call. This will be the only place you will have that snippet and it ensures that it runs on every request. It is also a catch-all for all Exceptions.

There are a few things that happen once the Exception is caught.

  1. (Line 33) Determine the id. This is used to log the Exception error and write in the response so an end-user can provide it back to a develop and they can easily find the error in the logs.
  2. (Line 37) Log the Exception error with the id.
  3. (Line 41) Call WriteExceptionResponseAsync() function to write the response back.

Inside the WriteExceptionResponseAsync() function, I create the AuthProblemDetail object with the Message, StatusCode and TraceId from the parameters.

Afterwards, check if the Exception thrown is an AuthException. If so, then replace the StatusCode, Message with the AuthException status code and message.

Finally, just update the httpContext status code, content type and write the response back.

That’s it! This is all you need to create an Exception middleware! Now, you can throw an Exception anywhere in your code and this will pick it up. For example, if a user’s password doesn’t match, then throw a BadRequest (400) Exception. The message will be returned to the user and the status code will be 400.

Throw AuthFriendlyException

--

--