Menu Close

Middleware in ASP .NET Core

This article explain Middleware in ASP.NET Core. Middleware is a piece of software that can handle an HTTP request or response. Each component chooses whether to pass the request on to the next component in the pipeline, and can perform certain actions before and after the next component is invoked in the pipeline. Request delegates are used to build the request pipeline, the request delegates handle each HTTP request. Please read my previous article ASP .NET Core Developer Exception Page.

middleware

As we know in the ASP .NET Core MVC when a user request through browser then sends it the web server means go the controller and do back response the client browser. Actually every request is filter through the HTTP pipeline called as Middleware that filter the user request and then sends to the corresponding component and sends back the response in same channel. Follow all the articles from basic to advance level explore ASP.NET Core Tutorials.

In ASP.NET Core there are so many built-in Middleware components are already available that you can directly use. If you want then you can also create your own Middleware components called it as custom middleware components. The most important point that you need to remember is, in ASP.NET Core a given Middleware component should only have use in a specific purpose.

We cover below points in this article

  • Where to use the Middleware Components in the ASP.NET Core application ?
  • How to Configure Middleware Components in ASP.NET Core application ?
  • Examples of using Middleware Components ?
  • What is the Execution Order of Middleware Components in ASP.NET Core ?

Where to use the Middleware Components in the ASP.NET Core application?

The middleware components may have use in below scenario.

  • We may have use Middleware component for authenticating the user.
  • Another Middleware component may be used to log the request and response.
  • Similarly, we may have a Middleware component that is used to handle the errors.
  • We may have a Middleware component that is used to handle the static files such as images, Javascript or CSS files, etc.
  • Also middleware can be used to Authorize the users while accessing a specific resource.

If you have worked with previous versions of ASP.NET then you may know, we use HTTP Handlers and HTTP Modules to set up the request processing pipeline, this pipeline which will determine how the HTTP request and response is going to be processed.

Similarly in ASP .NET Core, the Middleware components are the components that we use to set up the request processing pipeline in the ASP.NET Core application.

The below diagram illustrates the typical order of middleware layers in an ASP .NET Core web application. The order is very important, so it is necessary to understand the placement of each request delegate in the pipeline.

middleware Order

When an HTTP request comes in, the first request delegate handles that request. It chooses either passing the request on to the next component in the pipeline or performing certain actions before and after the next component is invoked in the pipeline. It allows unnecessary work to be avoided. This is very useful in some scenarios like handling exceptions before anything else or serving static files.

Let’s discuss the process flow the Middleware following the above image.

  • When a user request through browser it comes to Middleware1 and internally did some logic and if there is use next() method then it jump to Middleware2 else from Middleware1 the response is back.
  • If there is use next() in Middleware1 it go to Middleware2 and there do some other logic and if there is not use next() then the response is go back through Middleware1. If there is use next() in Middleware2 then it jump to Middleware3.
  • In Middleware3 some stuff is complete as we are not using next() here then it move back to Middleware2 then Middleware1 and finally response is back.
We can use “n” number of middleware in ASP .NET Core application.
But keep in mind that every middleware have the own separate logic.

Let’s prove this the above example in practically,

middleware-Process-Flow

Examples of Middleware Components ?

Middleware flow

In the above image we have taken into consideration of 3 middleware components.

we have a logging middleware component. This component simply logs the request time and then passes the request to the next middleware component i.e. Static Files Middleware component in the request pipeline for further processing.

A middleware component in ASP.NET Core may also handle the HTTP Request by generating an HTTP Response. The ASP.NET Core Middleware component may also decide not to call the next middleware component in the request pipeline. This concept is called short-circuiting the request pipeline.

For example, we have a static file middleware component. And if the incoming HTTP request comes for some static files such as images, CSS files, etc. then this Static Files Middleware component can handle the request and then short-circuit the request pipeline by not calling to the next component in pipeline i.e. the MVC Middleware component.

As we already discussed the ASP.NET Core middleware components can have access to both the HTTP request and response in the pipeline. So a middleware component can also process the outgoing response. For example, the logging middleware component in our case may log the time when the response is sent back to the client.

What are Run, Map and Use ?

Run, Map and Use are three methods that you will need to use to configure HTTP Pipeline.

Run method : Generate a response and short-circuit the request

The Run method is an extension method on IApplicationBuilder and accepts a parameter of RequestDelegate that handles the request. “Run” method enables short-circuiting with a terminal middleware delegate.

To confirm the short-circuiting let’s create a .NET core application with empty template and add a extension method into it and then access it in configure() like below;

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.Run(Mymiddleware);

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Hello World!");
            });
        }
        private Task Mymiddleware(HttpContext context) {
            return  context.Response.WriteAsync("Hello World from CoreProgram");
        }

Here Mymiddleware is the extension method and it is called in the configure() method. When we run the application you can see the result like below;

middleware result
Use method : Perform logic and send request to next part

This method allows you to call the next desired middleware delegate. The call to app.Use() can be used to trigger the next middleware component with a call to next.Invoke() as shown below:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.Use(async (context, next) =>
                {
                    await context.Response.WriteAsync("Hello World check from Use method!");
                    await next();
                });

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Hello World check from Run method!");
            });
        }

When we run the application you can see it print the result of app.Use instead of app.Run

use run result
Map method : Conditionally send the request to other middleware

This method is used to match request delegates based on a request’s path. This method allows branching of the pipeline path. In other words, this method creates separate paths/branches for your middleware pipeline and multiple terminating ends.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.Use(async (context, next) =>
                {
                    await context.Response.WriteAsync("Hello World check from Use method!");
                    await next();
                });
            app.Map("/custommap", CustomHandleMap);
            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Hello World check from Run method!");
            });
        }
        private static void CustomHandleMap(IApplicationBuilder app) {
            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Map method check with CustomHandleMap");
            });
        }

When we run the application and move to change the URL to custommap then the result look like below, it print use method text then it jump to custom map handle text.

Use map

What is the Execution Order of Middleware Components in ASP.NET Core ?

The ASP.NET Core middleware components are executed in the same order as they are added to the pipeline. So we need to take care when adding the middleware components to the request processing pipeline.

The following diagram shows the complete request processing pipeline for ASP.NET Core MVC and Razor Pages apps. You can see how, in a typical app, existing middlewares are ordered and where custom middlewares are added. You have full control over how to reorder existing middlewares or inject new custom middlewares as necessary for your scenarios.

middleware pipeline

Built-In Middleware

We should use the “Use” prefix naming convention when we create new custom Middleware. For example: UseFileUploadErrorPage, UseDebugErrorPage

Exception Handling
  • UseDeveloperExceptionPage() & UseDatabaseErrorPage(): used in development phase to catch run-time exceptions.
  • UseExceptionHandler(): used in production for run-time exceptions
HSTS & HTTPS Redirection
  • UseHsts(): used in production to enable HSTS (HTTP Strict Transport Security Protocol) and enforce HTTPS.
  • UseHttpsRedirection(): forces HTTP calls to automatically redirect to equivalent HTTPS addresses.

Calling these methods next ensure that HTTPS can be enforced before resources are served from a web browser.

Static files
  • UseStaticFiles(): used to enable static files, such as HTML, JavaScript, CSS and graphics files.

This Middleware is called early on to avoid the need for authentication, session or MVC middleware.

Cookie Policy:
  • UseCookiePolicy(): used to enforce cookie policy and display GDPR-friendly messaging
Authentication, Authorization & Sessions:
  • UseAuthentication(): used to enable authentication and then subsequently allow authorization.
  • UserSession(): manually added to the Startup file to enable the Session middleware.

Calling these after cookie authentication (but before the MVC middleware) ensures that cookies can be issued as necessary and that the user can be authenticated before the MVC engine kicks in.

MVC & Routing:
  • UseMvc(): enables the use of MVC in your web application, with the ability to customize routes for your MVC application and set other options.
  • routes.MapRoute(): set the default route and any custom routes when using MVC.

Conclusion

Leave behind your valuable queries and suggestions in the comment section below. Also, if you think this article helps you, do not forget to share this with your developer community. Happy Coding 🙂

Jayant Tripathy
Coder, Blogger, YouTuber

A passionate developer keep focus on learning and working on new technology.

Leave a Reply

Your email address will not be published.