Middleware In .NET Core

In this article, I will explain middleware concepts as follows

  1. What is middleware
  2. Middleware Order of Execution
  3. Create middleware using IApplicationBuilder
  4. Run, Use, and Map method
  5. Custom middleware
  6. Built-in middleware

What is middleware?

Middleware is just a simple class that consists of encapsulated information into an application pipeline to deal with the HTTP request-response pipeline.

Every part of this class has the option to pick whether to give the request to the next pipeline and can play out specific activities when the following request passes in the pipeline.

In this case, Request delegates are utilized to construct the request pipeline.

The request delegates handle every HTTP request.

Request delegates are designed to configure the Run, Map, and Use method on the IApplicationBuilder type that is passed into the Configure method in the Startup class. An individual request delegate can be determined in-line as a lambda expression, or it can be designed in a reusable class.

These reusable classes are middleware or middleware parts. Each middleware part in the request pipeline is liable for invoking the next pipeline or shortcircuiting the request.

Every component of middleware plays a specific role, we can mix up the role but this is not a good approach in software-designed architecture.

So we should create for the specific purpose of single middleware.

For example, we see how Microsoft created so much middleware for specific problems.

I will explain in just a bit about built-in middleware here.

Middleware Order of Execution

The middleware Order of Execution plays a very important role so you have to take care of it very precisely, otherwise you may get unexpected behavior.

So suppose you have 3 middleware - M1, M2, and M3 in sequential order, then it will invoke in the same order and then respond in the reverse direction.

Let's take another example here.

app.UseAuthentication();
app.UseAuthorization();

Here we have set first authentication then authorization, so the order matters, because in real projects we do first authentication, then authentication.

Please refer to this image as it is taken from MS doc reference.

Request

Create middleware using IApplicationBuilder

We can create middleware in the Configure method of the Startup class using the IApplicationBuilder interface.

Here in this following example, I will add a simple middleware using the Run method that will return a string "Hello my first middleware," on every request.

public class Startup {  
    public Startup() {}  
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) {  
        // here i have configure middleware using IApplicationBuilder with Run merhod.    
        // I will explain Run method in details just a bil.    
        app.Run(async (context) => {  
            await context.Response.WriteAsync("Hello my first middleware");  
        });  
        // I have removed hereother code for the clarity..    
    }  
}   

In this example, I have used the Run() method. This is an extension method of the IApplicationBuilder interface.

Here I have created middleware using lambda expression, but we can also create it using a private method like this.

public class Startup {  
    public Startup() {}  
    public void Configure(IApplicationBuilder app, IHostingEnvironment env) {  
        app.Run(TestMiddleware);  
    }  
    private Task TestMiddleware(HttpContext context) {  
        return context.Response.WriteAsync("Hello TestMiddleware");  
    }  
}   

Run, Use, and Map method

The run () method behaves like a terminal middleware delegate to the application's request pipeline.

It will not invoke the next one in the pipeline.

For example

// Middleware 1    
app.Run(async (context) => {  
    await context.Response.WriteAsync("Middleware 1");  
});  
// Middleware 2    
app.Run(async (context) => {  
    await context.Response.WriteAsync("Middleware 2");  
});   

So in this example, only // Middleware 1 will execute then after that it terminates the request.

When you right-click and go to the definition for the Run() method you will get this signature of Run method,

public static void Run (this is IApplicationBuilder app, RequestDelegate handler)

Use() is also a function of IApplicationBuilder that is used to handle the request or call the given next function.

So as we have seen in the Run() method it doesn't invoke the next function but Use does that.

public void Configure(IApplicationBuilder app, IHostingEnvironment env) {  
    app.Use(async (context, next) => {  
        await context.Response.WriteAsync("Middleware 1");  
        await next();  
    });  
    app.Run(async (context) => {  
        await context.Response.WriteAsync("Middleware 2");  
    });  
}   

I use first the Use method and then after that Run() method, so we will get the output for both Map() methods used for the branches of the request pipeline based on the matches condition.

If the request path matches with the given path, the branch is executed.

public void Configure(IApplicationBuilder app, IHostingEnvironment env) {  
    app.Map("/maptest", HandleMapMethod);  
}  
private static void HandleMapMethod(IApplicationBuilder app) {  
    app.Run(async context => {  
        await context.Response.WriteAsync("Map method testing");  
    });  
}   

Custom middleware

Here in this section, I will explain how to create and add your custom middleware.

Custom middleware is also kind of the same as built-in middleware but we create our own when a few requirements don't match with inbuilt middleware. In custom middleware, we should also have the RequestDelegate type parameter in the constructor.

Now at this time Microsoft in Visual Studio is provided a template for Middleware.

So for right click on your solution project or folder where you want to add a middleware class then select Add -> New Item. This will open Add the popup.

Search the word "middleware" in the top right search box and you will get the middleware template class.

Middleclass

public class MyCustomMiddleware {  
    private readonly RequestDelegate _next;  
    public MyCustomMiddleware(RequestDelegate next) {  
        _next = next;  
    }  
    public Task Invoke(HttpContext httpContext) {  
        // you can write here whatever you want    
        return _next(httpContext);  
    }  
}  
public static class MyMiddlewareExtensions {  
    public static IApplicationBuilder UseMyCustomMiddleware(this IApplicationBuilder builder) {  
        return builder.UseMiddleware < MyCustomMiddleware > ();  
    }  
}  

then you need to add your custom middleware in the configure method,

public void Configure(IApplicationBuilder app, IHostingEnvironment env) {  
    app.UseMyCustomMiddleware();  
    app.Run(async (context) => {  
        await context.Response.WriteAsync("Hello World!");  
    });  
}   

Built-in middleware

ASP.NET core provides the following middleware components,

Middleware Description
Authentication Provides authentication support.
CORS Configures Cross-Origin Resource Sharing.
Routing Defines request routes.

Session

Static Files

Diagnostics

MVC

Provides support for user sessions.

Provides support for serving static files and directory browsing.

Several separate middlewares provide a developer exception page, exception handling, status code pages, and the default web page for new apps.

Process requests with MVC/Razor Pages.

Thank you for taking your valuable time to read the full article.


Similar Articles