Exploring ASP.NET Core Middleware

Exploring ASP.NET Core Middleware

07 Aug 2024
Intermediate
47.4K Views
25 min read

Middle Ware in .Net Core: An Overview

Microsoft introduced a new feature called Middleware in the ASP.Net Core applications. Middleware is just a class or component that fires on every request received in the Asp.Net Core applications. In the previous version of the ASP.Net application, there are two different request pipelines, HttpHandlers and HttpModules. Middleware is similar to these HTTP action pipes which can be configured and executed on both sides. 

" Enroll in the ASP.NET Core Training Program from ScholarHat and start your tech career right away."

Read More: Top 50 ASP.NET Core Interview Questions and Answers for 2024

What is Middleware?

In Asp.Net Core, Middleware controls how applications behave on the HTTP request. Middleware depends upon classes which creates a pipeline that controls the request and response flow in the systems. Every section of the middleware can handle either request or response or both. Each section of the middleware also decides whether the related request or response will move to the next section of the pipeline.

In this way, we can develop a system flow with the help of middleware in the applications that handle the request situations that the core applications may not handle properly. On the official site of ASP.NET Core, Microsoft provides an excellent image in which they demonstrate the main behavior of the middleware –

What is Middleware?

So, in simple words, Middleware can:

  • Generate an HTTP response against the incoming HTTP request.
  • Can accept an incoming HTTP request, and then pass that request to the next middleware
  • Can populate an HTTP response and pass that response to another middleware or web server.

Read More: What is an ASP.NET Core Developer? Skills to become ASP.NET Core Developer

Architecture of Middleware

Architecture of Middleware

So every middleware component can execute any specific task before and after the next allotted component in the middleware pipeline is invoked. These request operations deleted can be configured using Run, Map, and Use extensions methods.

Any individual or independent request deleted can be executed or mentioned in-line as an anonymous method or it can also be defined as a reusable class. These reusable class or in-line anonymous methods are normally known as middleware components. So, every component in the middleware is responsible for executing the next component in the pipeline.

Built-In Middleware

Just like other features, Microsoft introduced so many inbuilt middleware with the Asp.Net Components. In this section, we will discuss some of the built-in middleware.

Middleware
Description
Order
Authentication
It is used to provide authentication support for the application.
It needs to be executed before HttpContext.User
CORS
It is used for configuring Cross-Origin Resource Sharing.
It needs to be executed before the execution of the COR-related components.
Diagnostics
It is used to configure diagnostics
It will execute before the components
Forwarded Headers
This middleware is used to forward proxy-related headers into the current request.
It needs to execute before component executions.
HTTP Method Override
This middleware provides us with the incoming POST request so that the method can be overwritten.
It will execute before the components consume this.
HTTPS Redirection
It is used to redirect all HTTP requests to the HTTP Service.
It will execute before the components consume these this.
HSTS
HSTS is one of the important middleware. HSTS stands for HTTP Strict Transport Security. This middleware layer increased the security with a special response header.
It needs to be executed before the response is sent to the middle or after the request is sent by the components.
MVC
This middleware normally handled all the requests sent or received from the MVC or Razor pages.
It is executed if the response matches the route.
Response Caching
This middleware provides support related to caching the response from the application
It needs to execute before any components which need to be cached.
Response Compression
This middleware compressed the response result which is received against any request.
It needs to execute before any components need to be compressed.
Request Localization
It provides localization support.
It needs to execute before any components which need to use localized data.
Routing
This middleware defines the request routes.
It needs to be executed when any route matches the response.
Session
This middleware provides support for maintaining or managing user login sessions.
It needs to execute before any components that need to use related data.
Static Files
This middleware provides support for accessing static files including directory browsing.
It needs to execute before any components match with the current solution.
URL Rewriting
This middleware provides support for rewriting the request URLs and also redirects the request to the next components.
It needs to execute the components before those components are consumed.
Web Sockets
This middleware is simply activated by the WebSocket’s protocol.
It needs to execute before any components accept WebSocket requests.

Configuring Middleware

So, if we want to use middleware in our application, then we need to configure middleware in our application. To do this, we need to use Configure() of the Startup class where we can use the instance of IApplicationBuilder. In the below example, we use a single middleware with the help of the Run method and it will return “Beginning to Middleware” as a string for each request.


public class Startup
{
 public Startup()
 {
 } 
 public void Configure(IApplicationBuilder application, IHostingEnvironment appEnv)
 { 
 application.Run(async (context) =>
 { 
 await context.Response.WriteAsync("Beginning to Middleware…"); 
 }); 
 }
}

In the above code block example, Run() is an extension of the IApplicationBuilder instance. This extension method adds middleware into the application request pipeline. This method accepts RequestDelegate parameters which handles any request into the application. The main signature of the Run() is as below –


public static void run (this IApplicationBuilder app, RequestDelegate handler)

Since this method accepts a RequestDelegate as a parameter, means that it can accept the HttpContext as a parameter and it return as a Task. That’s why we use lambda expression for returning the string in the above example. We can also specify a separate asynchronous function for returning the result and then that function needs to invoke within the Run() as below:-


public void Configure(IApplicationBuilder application, IHostingEnvironment appEnv)
{
 application.Run(FirstMiddleware);
}

private async Task FirstMiddleware (HttpContext context) 
{
 await context.Response.WriteAsync("Beginning to Middleware…");
}

Read More: Salary Offered to ASP.NET Developers

Similar to the above example, we can define multiple middleware components within the ASP.NET application that need to be executed sequentially. But for using multiple middleware, we can’t use the Run() since this method adds a terminal middleware. For that reason, it can’t be executing the next middleware.

In this situation, we need to use the Use() extension method to invoke multiple middleware components in our application. The signature of the Use() method is quite similar to the Run() method except that it accepts the next parameter to execute the next middleware components in the row. The below code demonstrates the same which will execute two middleware components.


public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
 application.Run(async (context,next) =>
{ 
 await context.Response.WriteAsync("Beginning to Middleware…"); 
}); 

application.Run(async (context) =>
{ 
 await context.Response.WriteAsync("Beginning Of Middlewar2"); 
});
}

Different Ways to Create Middleware

  1. Inline Middleware

  1. Here, you need to define the middleware inline within the Configure method of your Startup class. In the below example, we want to log incoming requests:

    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.Use(async (context, next) =>
        {
            // Log the incoming request
            LogRequest(context.Request);
            await next.Invoke();
            // Log the response
            LogResponse(context.Response);
        });
        // Other middleware and app configuration
    }    

    This inline middleware logs both the request and response details for every incoming request.

  1. Class-based Middleware

  1. This in ASP.NET Core is a way to create custom middleware components using classes. These middleware components are implemented as classes that implement the IMiddleware interface or derive from the Middleware base class.

    
    public class AuthenticationMiddleware
    {
        private readonly RequestDelegate _next;
        public AuthenticationMiddleware(RequestDelegate next)
        {
            _next = next;
        }
        public async Task InvokeAsync(HttpContext context)
        {
            // Perform authentication logic
            if (!context.User.Identity.IsAuthenticated)
            {
                context.Response.StatusCode = 401;
                return;
            }
            await _next(context);
        }
    }    

    In the Startup class, register and use this middleware:

    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseMiddleware();
        // Other middleware and app configuration
    }    
  2. Middleware Extension Methods

    To keep your Startup class clean, you can create extension methods for middleware.

    
    public static class AuthenticationMiddlewareExtensions
    {
        public static IApplicationBuilder UseAuthenticationMiddleware(this IApplicationBuilder app)
        {
            return app.UseMiddleware();
        }
    }    
    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseAuthenticationMiddleware();
        // Other middleware and app configuration
    }    
  3. Middleware Pipeline Ordering

    Order matters in middleware. The sequence in which you add middleware components to the pipeline affects their execution.

    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseExceptionHandler("/Home/Error");  // Error handling middleware
        // Other middleware and app configuration
    }    

How to Create a Custom Middleware in Asp.net Core?

So, as per the discussions till now, it is clear that middleware defines the current step process that needs to be executed, and also, after completing each step it is directed to the next step for further execution. So, as per our requirement, we need to build multiple middleware in the pipeline of requests, and writing all code within the configure() is not a good idea since it will not be extensible or clean.

We always want to define middleware as abstract or a separate file so that every middleware can perform a single type of responsibility. For that purpose, we first create a class named MyMessageMiddleware which will display some text messages before and after execution.


public class MyMessageMiddleware
{
 private readonly RequestDelegate _next;

 public MyMessageMiddleware (RequestDelegate next)
 {
 _next = next;
 }

 public async Task InvokeAsync(HttpContext context)
 {
 await context.Response.WriteAsync("!! Start of Custom Middleware !!\n\r");

 await _next(context);

 await context.Response.WriteAsync("\n\r!! End of Custom Middleware !!\");
 }
}

In the above class, we use the next RequestDelegate with the help of dependency injection as a part of the constructor. Also, we define a method named InvokeAsync which is as per the convention and we pass HttpContext as a parameter to this function. Also, we pass the HttpContext to execute the next delegate call.

Creating a Middleware Pipeline

Now, we need to create an extension method of IApplicationBuilder to define the custom middleware pipeline.


public static class MyMessageMiddlewareExtensions
{
 public static IApplicationBuilder UseMyMessageMiddleware(this IApplicationBuilder builder)
 {
 return builder.UseMiddleware<MyMessageMiddleware>();
 }
}

Now, implement this custom middleware extension method in the Startup class:


public class Startup
{
 public void ConfigureServices(IServiceCollection services)
 {
 }

 public void Configure(IApplicationBuilder application, IHostingEnvironment appEnv)
 {
 application.UseMyMessageMiddleware ();

 app.Run(async (context) =>
 {
 await context.Response.WriteAsync("Beginning to Middleware…");
 });
 }
}

Configuring the Middleware Pipeline

Configuring the middleware pipeline in ASP.NET Core involves adding and ordering middleware components to define how the application handles HTTP requests. This configuration is typically done in the Configure method of the Startup class.


public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

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

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

Middleware Components

  • Authentication Middleware: Handles authentication-related tasks, such as validating user credentials, issuing authentication tokens, and setting the user's identity principal.
  • Static File Middleware: Serves static files, such as HTML, CSS, JavaScript, and images, directly to clients without invoking the MVC pipeline.
  • Routing Middleware: Routes incoming requests to the appropriate endpoint based on URL patterns and HTTP methods.
  • Session Middleware: Manages user session data stored on the server side, enabling stateful interactions between requests.
  • Exception Handling Middleware: Catches unhandled exceptions thrown during request processing and generates appropriate error responses.
  • Cors Middleware: Implements Cross-Origin Resource Sharing (CORS) policies to control access to resources from different origins.
  • Compression Middleware: Compresses HTTP responses to reduce bandwidth usage and improve performance.
Summary

So in this article, we discuss the concept of Middleware, why it is required in .Net core applications, how we can configure it, and also how we can create custom middleware for our applications. So, we need to remember the key points related to the middleware:

  • Middleware represents a group of classes that forms a queue or pipeline for handling requests or responses.
  • The mentioned pipeline will end at the first execution of the app.Run().
  • We want to use multiple middleware, then we can use apps.Use()
  • We can create extension methods of IApplicationBuilder to include custom middleware in our application.

Get ready for 100% growth in your tech career! Our .NET Core Certification Course guarantees you the skills you need for a salary hike, job placement, and interview success. Enroll today and watch your future soar!

FAQs

Middleware refers to software components that intercept and process HTTP requests and responses in an application.

In ASP.NET Core, middleware intercepts HTTP requests and responses as they flow through the application pipeline.

  • Authentication Middleware
  • Authorization Middleware
  • Logging Middleware
  • Static File Middleware
  • Routing Middleware
  • Cors Middleware
  • Compression Middleware

  1. Request Processing Middleware
  2. Diagnostic Middleware
  3. Security Middleware
  4. Compression Middleware
  5. CORS Middleware

UseAuthentication middleware

Take our Aspnet skill challenge to evaluate yourself!

In less than 5 minutes, with our skill challenge, you can identify your knowledge gaps and strengths in a given skill.

GET FREE CHALLENGE

Share Article
About Author
Debasis Saha (Technical Manager, Author and Mentor)

He is an ASP.Net, MVC and Angular Technical Manager with 10 years of experience. He always been a great fan of Microsoft Technologies and loves working on them. He has expertise in Asp.Net, MVC, SQL Server, MongoDB, Angular JS, and Angular. He loves to write articles about these technologies.
Accept cookies & close this