• Jeff Fillegar
  • Posts
  • How to add Custom Middleware and Global Exception Handling to a .NET 6 API?

How to add Custom Middleware and Global Exception Handling to a .NET 6 API?

Introduction

Developed as open source by Microsoft, the .Net Core library provides many conveniences and advantages to developers. One of the most important innovations that entered our world with .Net Core is the concept of middleware.

In this article, we will examine the concept of middleware that we met with .Net core, then we will see how to easily control an application with JWT inclusion developed with Asp.Net Core 6 using middleware. Finally, we will use middleware as a global exception handler. So let’s get started.

Code on GitHub

Don’t want to wait? Get the complete source of the application I developed for this blog post on GitHub here: https://github.com/fillegar/dotnet-6-crud-api-jwt-sql-server

What is Middleware?

Where is Middleware Used?

Middleware structures are modular structures that allow Methods defined as Extensions to a Class derived from the IApplicationBuilder Interface to be run in the desired order. Along with these structures;

  • It can be ensured that the requests are passed through the desired controls

  • It can be ensured that the responses are derived from the cache

  • We can create logging mechanisms on the application

  • Solutions can be provided for exception handling

How to Write Custom Middleware?

In addition to these features, of course, if we want to perform certain operations on the incoming request, we can write custom middleware ourselves.

It is sufficient to create a class for the custom middleware and create a structure like the one below. Below is the function that will contain the business logic to be applied on the requests in the invoke method in the class and will be triggered automatically when the middleware is called. With the Invoke method of the RequestDelegate object injected in the constructor, we call the next middleware in the middleware pipeline and transfer our httpContext to it.

To include the middleware in the pipeline, it will be sufficient to add the following line of code to the Program class.

As it is understood, we can handle request and response by performing operations on request and response with middleware. There are 3 types of methods used to interact with request.

  • Use

  • Run

  • Map

Use Method

This method gives us a delegate named next as seen below. With this we can access the next middleware member. It can be used to get between two middleware objects.

Output will be “One, Three, Two”.

Run Method

It is possible to short-circuit the pipeline with run. After the request falls into this method, other processes on the pipeline do not continue and do not pass through other middlewares.

In the code block here, we can see that the text “One” is written to the screen and terminates without falling into the other run method.

Map Method

As the name suggests, we use the Map method when we want to capture a path. When we want to place a business logic for the map named branch as below, we can follow a path as follows.

Code

In this section, we will cover how to add both token validation and global exception handling mechanism in a short way using middleware of an application developed with .Net Core 6 and manually validating JWT.

The application normally uses the Postgresql database in its development environment. We will use Sql Server for the production environment and we will perform our tests here. For the production environment, we will create a file named ‘appsettings.Production.json’ under the ‘appsettings.json’ file. In this file we will paste all the information in the ‘appsettings.Development.json’ file, then replace the database connection connectionString with the Sql Server connection information

Now we will add the Sql Server library for Entity Framework Core to the ‘User.Repository’ layer. We will download and install the Microsoft.EntityFrameworkCore.SqlServer library from NuGet on the ‘User.Repository’ layer.

nuget-entityframework-core-sqlserver

Then we will paste the following codes into Program.cs for database adjustments according to the environment.

At this stage, we need to migrate the Sql Server ‘UserInfo’ entity to the Sql Server database. First, let’s update the ‘ASPNETCORE_ENVIRONMENT’ values in the ‘launchSetting.json’ file to ‘Production’. Then, let’s select the default project ‘User.Repository’ from the package manager console and run the following commands respectively and perform the migration of the Sql Server database.

Add-Migration MigrateSqlDb

Update-Database

Then we will add the ‘ValidateToken’ method from the ‘TokenUtilsHandler.cs’ class that generates the token, where we will perform token validation.

Let’s move on to creating custom middleware. We will create custom middleware for JWT validation. In the ‘User.API’ project we will create a folder named ‘Middlewares’ and create a class called ‘JwtMiddleware’ in it. Let’s paste the following codes into the custom middleware class we created.

After creating the custom middleware class, we will expand and use the [Authorize] attribute, which we will use in endpoints that only authorized users can access.

We will open a folder named ‘Attribute’ to the ‘User.Core’ project and create a class named ‘AuthorizeAttribute’ in it. Let’s paste the following code into the class we created.

To use the extended [Authorize] attribute, we will create a Web API named ‘CategoryController’ in the ‘User.API’ project and put the following codes in it.

Before adding the Jwt Middleware we created to ‘Program.cs’, let’s create a middleware for global exception handling.

Let’s create a class named ‘GlobalExceptionHandlerMiddleware’ in the folder named ‘Middlewares’ that we created before and write the following codes.

Let’s add the ‘UserInfoNotFoundException’ class, which is our custom exception, to the login endpoint.

Now, as the last step, we will add the custom middlewares we created to ‘Program.cs’. The final version of the ‘Program.cs’ class will be as follows.

Test

Now we will test the application with the Production environment. After running the application, we will first create a user. Let’s create a user via Postman as follows.

We will login with the user we created and we will obtain a access token.

Now we will send a request to the /api/category endpoint with the token information we have obtained.

user-auth

We have successfully obtained the category information. Now we will try to send a request from Postman without authorizing information.

user-unauth

With the custom JWT middleware we created and the authorize attribute that we expanded, we successfully performed token validation in an easy way.

Finally, to test the custom middleware, the global exception handling middleware, we will try to log in with an email that is not in the database.

We saw that our global exception handler is running successfully.

Conclusion

In this article, we touched on the concept of middleware that we met with .Net Core and we handled the JWT flow in an existing .Net core application in an easy way with middleware. In addition, we have included our middleware and global exception handler in our application in two steps. You can find more information about .net middleware here.

Code on Github

Get the complete source of the application we developed in this article, on GitHub here:https://github.com/fillegar/dotnet-6-crud-api-jwt-sql-server