ASP.NET Core Middleware Components

ASP.NET Core Middleware with Examples

In this article, I will discuss the ASP.NET Core Middleware Components with Examples. Please read our previous article discussing the ASP.NET Core AppSettings.json File with Examples. As part of this article, we will discuss the following concepts related to the ASP.NET Core Middleware Components.

  1. What are the ASP.NET Core Middleware Components?
  2. Where do we use the Middleware Components in the ASP.NET Core application?
  3. How do you configure Middleware Components in the ASP.NET Core application?
  4. Examples of using Middleware Components?
  5. What is the Execution Order of Middleware Components in ASP.NET Core?
  6. What are Request Delegates in ASP.NET Core?
  7. What is Use, Run, and Map Methods in ASP.NET Core?
  8. What is the UseDeveloperExceptionPage Middleware Component?
  9. How do you configure Middleware components using the Run() and Use() Extension Methods?
  10. What is the difference Between MapGet and Map Methods?
  11. What are the differences between Map, Use, and Run Extension Methods?
What are ASP.NET Core Middleware Components?

ASP.NET Core Middleware Components are the basic building blocks of the request processing pipeline in an ASP.NET Core application. Middleware components handle specific tasks while processing incoming HTTP requests and outgoing HTTP responses. They enable us to add various functionalities to our application, such as Authentication, Routing, Logging, Exception Handling, etc.

Where Do We Use Middleware Components in the ASP.NET Core Application?

Some of the examples of using Middleware components in the ASP.NET Core application are as follows.

  1. We have a Middleware component (UseAuthentication) for authenticating the user.
  2. We have a middleware component (UseHttpsRedirection) for redirecting HTTP Requests to HTTPS.
  3. Another Middleware component (UseHttpLogging) logs the HTTP Requests and Responses.
  4. Another Middleware component (UseDeveloperExceptionPage) will execute when an unhandled exception occurs in the development environment. 
  5. Similarly, we have a Middleware Component (UseExceptionHandler) that is used to catch exceptions, log them, and re-execute the request in an alternate pipeline.
  6. We have a Middleware component (UseStaticFiles) that handles static files such as Images, Javascript, CSS files, etc.
  7. We have a Middleware component (UseAuthorization) that authorizes users to access a specific resource.
How do you configure Middleware Components in the ASP.NET Core (.NET 6) application?

From .NET 6, we need to configure the Middleware components within the Main() method of the Program class, which is present inside the Program.cs class file. This class will run when the application starts, and application execution will start from the Main method, which is the entry point for any ASP.NET Core Web Application.

When we create a new ASP.NET Core Empty Web Application, the Program class is created with the Main method by default, as shown in the image below.

ASP.NET Core 6 Main Method

In the above Main method, by default, we have configured two middleware components, i.e., MapGet and Run. Suppose you want to configure a new middleware component; in that case, you need to configure it within the Main() method of the Program class. For a better understanding, please modify the Main Method of the Program class as follows. Here, we have configured a few Middleware Components using the WebApplication instance (using the variable app), such as UseDeveloperExceptionPage(), UseRouting(), and UseEndpoints().

namespace FirstCoreWebApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            var app = builder.Build();

            //Configuring Middleware Components into Application Request Processing Pipeline

            //Configuring UseDeveloperExceptionPage Middleware Component if the Environment is Development
            if (app.Environment.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            //Configuring UseRouting Middleware Component
            //It matches a request to an endpoint.
            app.UseRouting();

            //Configuring UseEndpoints Middleware Component
            //It executes the matched endpoint.
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            });

            app.Run();
        }
    }
}

As you can see in the above code, the Main() method sets up the request processing pipeline with a few middleware components as follows.

  1. UseDeveloperExceptionPage() Middleware component
  2. UseRouting() Middleware component
  3. UseEndpoints() Middleware component

Before understanding the above Built-in Middleware Components in ASP.NET Core Applications, let us first understand what Middleware Components are and How Exactly These Middleware Components Work in ASP.NET Core Web Applications.

How Does the Middleware Component Works in the ASP.NET Core Application?

In the ASP.NET Core Web Application, the Middleware Component can access the incoming HTTP Request and outgoing HTTP Response. So, a Middleware Component in ASP.NET Core Web Application can

  1. Handle the incoming HTTP request by generating an HTTP response.
  2. Process the incoming HTTP request, modify it, and then pass it to the Next Middleware Component that is configured in the Application Request Processing Pipeline.
  3. Process the outgoing HTTP response, modify it, and then pass it on to either the previous middleware component or the ASP.NET Core Web Server.

For better understanding, please have a look at the following diagram, which shows how the middleware components are used in the Request Processing Pipeline of the ASP.NET Core Web Application. As shown in the image below, we have configured 3 Middleware Components to the Application Request Processing Pipeline to handle HTTP Requests and Responses.

Understanding Middleware Components in ASP.NET Core

We have a Logging Middleware Component. This component logs the request time and then passes the HTTP Request to the next middleware component, i.e., the Static Files Middleware component in the Request Pipeline, for further processing.

As previously discussed, a Middleware Component in an ASP.NET Core Web Application may also handle the HTTP Request by generating an HTTP Response. The Middleware Component may also decide not to call the Next Middleware Component in the Request Processing Pipeline, a concept called Short-Circuiting the Request Processing Pipeline.

For example, we have a Static Files Middleware Component. Suppose the incoming HTTP request comes for some static files such as images, CSS files, JavaScript, etc. In that case, this Static Files Middleware component can handle the request and then Short-Circuiting the Request Processing Pipeline by not calling the Next Middleware Component in the pipeline, i.e., the MVC Middleware Component.

As we already discussed, the ASP.NET Core Middleware Components can access 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 is the Execution Order of Middleware Components in ASP.NET Core Application?

It is very important to understand the execution order of Middleware Components in ASP.NET Core Web Applications. The ASP.NET Core Middleware Components are executed in the same order as they are added to the Request Processing Pipeline, so we need to take proper care when adding them to the Request Processing Pipeline of the ASP.NET Core Web Application.

As per your Application’s Business Requirements, you may add any number of Middleware Components. For example, if you are developing a static web application with static HTML pages and images, you may require only “StaticFiles” middleware components in the Request Processing Pipeline.

However, if you are developing a secure Dynamic Data-Driven Web Application, you may require several Middleware Components, such as Logging, Authentication, Authorization, MVC, etc.

What are Request Delegates in ASP.NET Core?

In ASP.NET Core, Request Delegates are used to build the Request Processing Pipeline, i.e., to handle each incoming HTTP request. You can configure the Request Delegates using the Run, Map, and Use Extension Methods.

You can specify a Request Delegate using an in-line anonymous method (called in-line middleware) or specify the Request Delegates using a reusable method. These reusable methods and in-line anonymous methods are called Middleware or Middleware Components. Each Middleware Component in the Request Processing Pipeline is responsible for invoking the Next Middleware Component in the Pipeline or Short-Circuiting the Pipeline by not calling the Next Middleware Component.

What is the use of the Use and Run Extension Method in ASP.NET Core Web Application?

In the ASP.NET Core Web Application, we can use the “Use” and “Run” Extension Methods to register the Inline Middleware Component into the Request Processing Pipeline. The “Run” extension method allows us to add the terminating middleware (the middleware that will not call the Next Middleware Components in the Request Processing Pipeline) component. On the other hand, the “Use” extension method allows us to add the middleware components, which may call the next Middleware Component in the Request Processing Pipeline.

If you observe the Main method of the Program class, you will see that it gets an instance of WebApplication, and using the WebApplicatio instance (app) along with the extension methods such as Use and Run, it configures the Middleware Components. As you can see, in the Main method of the Program class, three Middleware Components are registered into the Request Processing Pipeline. They are as follows:

  1. UseDeveloperExceptionPage() Middleware Component
  2. UseRouting() Middleware Component
  3. UseEndpoints() Middleware Component
What is the DeveloperExceptionPage Middleware Component?

The UseDeveloperExceptionPage() Middleware Component will appear only when the hosting environment is set to Development. This middleware component will execute when an unhandled exception occurs in the application. Since it is in Development mode, it will show you the exception details on the webpage. You can consider this a replacement for the Yellow Screen of Death. In a later article, we will understand how to use this middleware component in detail.

What is the UseRouting() Middleware Component?

The UseRouting() middleware component adds Endpoint Routing to the request processing pipeline. Endpoint Routing means it will map the URL (or incoming HTTP Request) to a particular resource. We will discuss this in detail in our Routing articles.

What is the UseEndpoints() Middleware Component?

To use the UseEndpoints() Middleware Component, you must first add the UseRouting() middleware component. In this UseEndpoints() Middleware Component, the Map extension method will take the routing decisions. As part of this UseEndpoints() Middleware Component, we can register multiple URL patterns using the MapGet or Map methods.

For a better understanding, please have a look at the following example. As you can see, in the MapGet Extension Method, we have specified multiple URL patterns like “/”, “/api”, and “/home”. So, based on the URL pattern, the corresponding middleware component will be executed.

namespace FirstCoreWebApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            var app = builder.Build();

            //Configuring UseRouting Middleware Component
            //It matches a request to an endpoint.
            app.UseRouting();

            //Configuring UseEndpoints Middleware Component
            //It executes the matched endpoint.
            app.UseEndpoints(endpoints =>
            {
                //URL: https://localhost:44333/
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });

                //URL: https://localhost:44333/api
                endpoints.MapGet("/api", async context =>
                {
                    await context.Response.WriteAsync("Hello World! From API");
                });

                //URL: https://localhost:44333/home
                endpoints.MapGet("/home", async context =>
                {
                    await context.Response.WriteAsync("Hello World! From Home");
                });
            });

            //This will Run Application
            app.Run();
        }
    }
}

Instead of MapGet, you can also use the Map method, as shown below.

namespace FirstCoreWebApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            var app = builder.Build();

            //Configuring UseRouting Middleware Component
            //It matches a request to an endpoint.
            app.UseRouting();

            //Configuring UseEndpoints Middleware Component
            //It executes the matched endpoint.
            app.UseEndpoints(endpoints =>
            {
                //URL: https://localhost:44333/
                endpoints.Map("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });

                //URL: https://localhost:44333/api
                endpoints.Map("/api", async context =>
                {
                    await context.Response.WriteAsync("Hello World! From API");
                });

                //URL: https://localhost:44333/home
                endpoints.Map("/home", async context =>
                {
                    await context.Response.WriteAsync("Hello World! From Home");
                });
            });

            //This will Run Application
            app.Run();
        }
    }
}

Now run the application, and you should get the output as expected.

  1. UseRouting(): It matches a request to an endpoint.
  2. UseEndpoints(): It executes the matched endpoint.
What is the Difference Between MapGet and Map Extension Methods in ASP.NET Core?

In ASP.NET Core, both MapGet and Map extension methods are used for configuring request handling in the application’s routing system, but they serve slightly different purposes and have different use cases.

MapGet Method:
  • Purpose: MapGet is specifically designed to handle HTTP GET requests. It’s used to define endpoints that respond only to GET requests.
  • Usage: You typically use MapGet when you want to retrieve data from the server without modifying its state, such as fetching a list of items or getting details about a specific item.
Map Method:
  • Purpose: Map handles all types of HTTP requests (GET, POST, PUT, DELETE, etc.). 
  • Usage: You use Map when you need to set up endpoints that might handle multiple types of HTTP requests or when you have custom logic to determine the type of request to be handled.

Note: Once we progress in this course, we will discuss handling GET, POST, PUT, & DELETE requests using the Map method.

How do you configure Middleware components using the Run() Extension Method?

Now, let us see how to configure new Middleware Components using the Run Extension Method in the ASP.NET Core Web Application. From the .NET 6, we need to configure the Middleware Components within the Main method of the Program class. So, modify the Main method of the Program class as follows to add a new custom Inline Middleware Component using the Run Extension Method.

namespace FirstCoreWebApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            var app = builder.Build();

            //Configuring New Inline Middleware Component using Run Extension Method
            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Getting Response from First Middleware");
            });

            //This will Start the Application
            app.Run();
        }
    }
}

Now, run the application, and you should get the expected output, as shown in the image below.

Middleware Components in ASP.NET Core Application

If you go to the definition of the Run Extension Method configuring the Middleware Component, you will see the following signature. It basically adds a terminal middleware delegate to the application’s request pipeline.

Run Extension Method Definition in ASP.NET Core

Here, you can see it is clearly saying that this Extension Method is used for adding terminal middleware. Terminal Middleware is the last middleware component. If you are new to the extension method, please read the article below, where we discussed the extension methods in detail.

https://dotnettutorials.net/lesson/extension-methods-csharp/

You can also see from the above definition of the Run() Extension method that it takes an input parameter of RequestDelegate. Now, if you go to the definition of RequestDelegate, then you will see the following.

RequestDelegate in ASP.NET Core

As you can see in the above image, the RequestDelegate is a delegate that takes an input parameter of type HttpContext object. If you are new to delegates, I strongly recommend reading the following article, which discusses them in detail.

https://dotnettutorials.net/lesson/delegates-csharp/

As we already discussed, the middleware components in an ASP.NET Core Web Application can access both HTTP requests and Responses because of the HttpContext object. In our example, we pass an anonymous or delegate method to the Run Extension method. Moreover, we pass the HTTP Context object as an input parameter to the request delegate. The following diagram shows the above.

ASP.NET Core Middleware Components with Examples

Note: Instead of passing the request delegate inline as an anonymous method, you can also define it in a separate class and pass it here, which we will discuss later.

Add one More Middleware Component to the Application Request Processing Pipeline.

To do so, modify the Main method of the Program class as shown below.

namespace FirstCoreWebApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            var app = builder.Build();

            //Configuring New Middleware Component using Run Extension Method
            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Getting Response from First Middleware");
            });

            //Configuring New Middleware Component using Run Extension Method
            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Getting Response from Second Middleware");
            });

            //This will Run Application
            app.Run();
        }
    }
}

Now, we have two middleware components registered with the Run() extension method. If you run the application, then you will get the following output.

Getting Response from First Middleware

The output comes from the first middleware component. We register the middleware component using the Run() extension method. That component becomes a terminal component, which means it will not call the next middleware component in the request processing pipeline.

Configuring Middleware Components Using the Use Extension Method

Then, you may wonder how to call the next component in the request processing pipeline. The answer is to register your middleware component using the Use extension method, as shown below. In the first Use Extension method, we pass two input parameters to the anonymous method, i.e., context and next. Then, we call the next method, which will call the next middleware component registered in the Request Processing Pipeline.

namespace FirstCoreWebApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            var app = builder.Build();

            //Configuring New Middleware Components using Use Extension Method
            app.Use(async (context, next) =>
            {
                await context.Response.WriteAsync("Getting Response from First Middleware");
                await next();
            });

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("\nGetting Response from Second Middleware");
            });

            //This will Run Application
            app.Run();
        }
    }
}

Now run the application, and you will see the output as expected, which comes from both the middleware components, as shown in the image below.

Configuring Components using Use Extension Method in ASP.NET Core

Understanding the Use Extension Method in ASP.NET Core:

The Use extension method adds a middleware delegate defined in-line to the application’s request pipeline. Following is the definition of the Use extension method:

Understanding the Use Extension Method in ASP.NET Core

This method has also been implemented as an extension of the IApplicationBuilder interface. This is the reason why we can invoke this method using the IApplicationBuilder instance. As you can see from the above definition, this method takes two input parameters. The first parameter is the HttpContext context object, through which it can access both the HTTP request and response. The second parameter is the Func type, i.e., it is a generic delegate that can handle the request or call the next middleware component in the request pipeline. 

Note: If you want to send the request from one middleware to the next, you need to call the next method.

Differences Between Run, Map, and Use Extension Method in ASP.NET Core:
Use Extension Method:
  • Middleware components added using Use can handle requests and then pass them on to the next component in the pipeline (by calling the next delegate). This makes it flexible for tasks like logging, authentication, etc.
  • Example: Adding a custom logging middleware.
Run Extension Method:
  • The Run Extension method adds a terminal middleware to the request pipeline. This means it does not call the next middleware in the pipeline. Since Run is a terminal operation, it is used when the response is fully formed and ready to be returned to the client. 
  • Example: Returning a static file directly or a simple message at the end of the pipeline.
Map Extension Method:
  • The Map Extension method branches the pipeline based on the request path. When a request matches a specified path, the Map delegate handles it. Requests that don’t match the path continue through the main pipeline.
  • Example: Mapping different routes to different middleware pipelines, like /api going to API-specific middleware and /home going to UI-specific middleware.

In the next article, I will discuss the ASP.NET Core Request Processing Pipeline with Examples. In this article, I explain How to use Middleware Components in the ASP.NET Core Application to handle the request processing pipeline with an example. I hope you enjoy this article on ASP.NET Core Middleware Components with Examples.

5 thoughts on “ASP.NET Core Middleware Components”

Leave a Reply

Your email address will not be published. Required fields are marked *