ASP.NET Core Request Processing Pipeline

ASP.NET Core Request Processing Pipeline

In this article, I am going to discuss the ASP.NET Core Request Processing Pipeline with an example. Please read our previous article before proceeding to this article where we discussed How to Configure Middleware Components in ASP.NET Core application. As part of this article, we are going to discuss the following pointers in detail.

  1. Understanding the ASP.NET Core Request Processing Pipeline.
  2. How to create and register multiple middleware components in ASP.NET Core?
  3. What is the execution order of middleware components in the request processing pipeline?
Understanding the ASP.NET Core Request Processing Pipeline:

In order to understand Request Processing Pipeline in ASP.NET Core, concept, let us modify the Configure() method of the Startup class as shown below. Here we are registering three middleware components into the request processing pipeline. As you can see the first two components are registered using the Use() extension method and the last one is registered using the Run() extension method. 

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

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

        public void Configure(IApplicationBuilder app, IHostingEnvironment env,
                ILogger<Startup> logger)
        {
            app.Use(async (context, next) =>
            {
                logger.LogInformation("Middleware1: Incoming Request");
                await next();
                logger.LogInformation("Middleware1: Outgoing Response");
            });

            app.Use(async (context, next) =>
            {
                logger.LogInformation("Middleware2: Incoming Request");
                await next();
                logger.LogInformation("Middleware2: Outgoing Response");
            });

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Middleware3: Incoming Request handled and response generated");
                logger.LogInformation("Middleware3: Incoming Request handled and response generated");
            });
        }
    }
}
Code Explanation:

First, we inject the logging middleware i.e. ILogger<Startup> into the Configure() method. The CreateDefaultBuilder() method of the Program class which is called by the Main() method configures the logging. As ASP.NET Core is open source, so you can verify this by visiting the following link

https://github.com/aspnet/MetaPackages/blob/release/2.2/src/Microsoft.AspNetCore/WebHost.cs

Somewhere within the code, you will find the ConfigureLogging() method as shown below

ASP.NET Core Request Processing Pipeline ConfigureLogging

As shown in the above image, the logger is configured for Console, Debug and EventSource. In our example, we are using the logger instance which is provided through Dependency Injection to log the information.

If you are running your application using .NET Core CLI, then you can see the logged information on the Console window whereas if you are running your application directly from Visual Studio, then you can see the logged information in the output window.

Now run the application, select the Debug option from the drop-down list of the Output window as shown below to see the logged information.

ASP.NET Core Request Processing Pipeline

Here you need to keep the focus on the order on which it logged information. It logged the information in the following order.

Middleware1: Incoming Request

Middleware2: Incoming Request

Middleware3: Incoming Request handled and response generated

Middleware2: Outgoing Response

Middleware1: Outgoing Response

Understanding the ASP.NET Core Request Processing pipeline Order:

In order to understand this, let us compare the above output with the following diagram to understand the ASP.NET Core Request Processing Pipeline.

ASP.NET Core Request Processing pipeline Order

When the incoming HTTP request comes, first it receives by the first middleware component i.e. Middleware1 which logs “Middleware1: Incoming Request” so as a result first we see this message first on the output window.

Once the first middleware logs the information, then it calls next() method which will invoke the second middleware in the request processing pipeline i.e. Middleware2.

The second middleware logs the information “Middleware2: Incoming Request” as a result we see this log information after the first log. Then the second middleware calls the next() which will invoke the third middleware in the request pipeline which is Middleware3.

The third middleware handles the request and then produces the response. So, the third information that we see in the output window is “Middleware3: Incoming Request handled and response generated”.

As this middleware component is registered using the Run() extension method, so it is a terminal component. So from this point, the request pipeline starts reversing. That means from this middleware, the control is given back to second middleware and the second middleware logs the information as “Middleware2: Outgoing Response” and then give the control back to the first middleware component and the first middleware component logs the information as “Middleware1: Outgoing Response

Key Points to remember:

The ASP.NET Core request processing pipeline consists of a sequence of middleware components which are going to be called one after the other.

Each middleware component can perform some operations before and after invoking the next component using the next delegate. A middleware component can also decide not to call the next middleware component which is called as short-circuiting the request pipeline.

The middleware component in asp.net core has access to both the incoming request and the outgoing response.

The most important point that you need to keep in mind is the order in which the middleware components are added in the Configure method of the Startup class defines the order in which these middleware components are going to be invoked on requests and the reverse order for the response. So, the order is critical for defining security, performance, and functionality of the application.

In the next article, I am going to discuss how to handle the static files in ASP.NET Core using Static Files middleware components. Here, in this article, I try to explain the ASP.NET Core Request Processing Pipeline with an example. I hope this article will help you to understand the Request Processing Pipeline in ASP.NET Core Web Application. 

Leave a Reply

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