Middleware in ASP.net

  • by

Middleware

Before moving on to the next file, let’s see more about the Middlewares in ASP dotnet core. Middlewares are one of the important and outstanding features of ASP dotnet core. Middlewares are small software modules that are executed on top of the actual application business logic. They are present one after the other like a pipeline where the output of one module is passed on to the next one. Yes, from the above statement we can infer that it is possible for us to have multiple middlewares in our application.

Each middleware component chooses or decides whether the output can be passed on to the next component.

The pipelines in the middleware are created using the request delegates. These request delegates handle the http requests that are encountered by our application. Like shown in the figure each middleware module has logic that can be executed before and after a call is made to the next middleware module.

The middleware logic is executed using the Run, Use and Map extension methods.For example when we have to add a single middleware to our application we can use the Run method in the following way.

public class Startup

{

   public void Configure(IApplicationBuilder app)

   {

       app.Run(async context =>

       {

           await context.Response.WriteAsync(“Hello, World!”);

       });

   }

}

When the application is run with the above code, each time when a Http request hits, this middleware gets executed and Hello, World ! will be printed in the console. 

When we have to create a pipeline with multiple middlewares then we can make use of the Use extension method.Like the following code fragment 

public class Startup

{

   public void Configure(IApplicationBuilder app)

   {

       app.Use(async (context, next) =>

       {

           // Do work that doesn’t write to the Response.

           await next.Invoke();

           // Do logging or other work that doesn’t write to the Response.

       });

       app.Run(async context =>

       {

           await context.Response.WriteAsync(“Hello from 2nd delegate.”);

       });

   }

}

As depicted here, next is the parameter that represents the next middleware in the pipeline that needs to be executed. Also it is possible to perform operations before and after the next delegate or middleware in line has been called. There are two things a delegate can do, either call the next delegate in line or do a short circuiting. When a delegate or middleware decides not to call the next delegate or stops execution without calling the next delegate it’s called short circuiting the request pipeline.

The run extension method is always terminal, i.e., it does not take next as a parameter and terminates the pipeline.In the given example, the console will have the output,”Hello from 2nd delegate.”, if it was otherwise, if Use was given after the Run, then the code under the Use extension method will not get executed.

There is one more extension method called the Map extension. This method is used for branch pipelines. Whenever the request path matches with the given path the branch pipeline gets executed.

public class Startup

{

   private static void HandleMapTest1(IApplicationBuilder app)

   {

       app.Run(async context =>

       {

           await context.Response.WriteAsync(“Map Test 1”);

       });

   }

   private static void HandleMapTest2(IApplicationBuilder app)

   {

       app.Run(async context =>

       {

           await context.Response.WriteAsync(“Map Test 2”);

       });

   }

   public void Configure(IApplicationBuilder app)

   {

       app.Map(“/map1”, HandleMapTest1);

       app.Map(“/map2”, HandleMapTest2);

       app.Run(async context =>

       {

           await context.Response.WriteAsync(“Hello from non-Map delegate. <p>”);

       });

   }

}

Here in the above example, if the http request has /map1, “Map Test 1” is logged in the console and if the http request has /map2, “Map Test 2” is logged in the console, if the request matches with none of the mentioned ones then by default “Hello from non-Mao delegate. <p>” is printed in the console.

Writing Custom Middleware

There are two types of middleware possible. The built in middleware offered by the dotnet framework and the custom middleware that can be provided by the user building the app.When we have to write a custom middleware, there are two classes that are mandatory, one is the class that contains the implementation of the middleware and the other one is the extension class that registers this middleware in the request pipeline.

The middleware class should have either of the following methods, Invoke or InvokeAsync and should have Request Delegate as a parameter through the constructor. The Invoke and InvokeAsync methods should take in the Http Context as a parameter and should return Task as output.

For example a middleware class implementation to set the country variable of the user information from the current request.

namespace Country

{

   public class RequestCountryMiddleware

   {

       private readonly RequestDelegate _next;

       public RequestCountryMiddleware(RequestDelegate next)

       {

           _next = next;

       }

       public async Task InvokeAsync(HttpContext context)

       {

           var country = context.Request.Query[“country”];

           if (!string.IsNullOrWhiteSpace(country))

           {

               var userInformation = new UserInformation();

               userInformation.Country = country;

           }

           // Call the next delegate/middleware in the pipeline

           await _next(context);

       }

   }

}

The extension class for this would be as follows

using Microsoft.AspNetCore.Builder;

namespace Country

{

   public static class RequestCountryMiddlewareExtensions

   {

       public static IApplicationBuilder UseRequestCountry(

           this IApplicationBuilder builder)

       {

           return builder.UseMiddleware<RequestCountryMiddleware>();

       }

   }

}

The UseMiddleware method is the one that registers the custom middleware that we have written in the request pipeline. Once these two are done our middleware is good to be called from the StartUp class’s configure method using the line app.UseRequestCountry();. Our custom middlewares are the ones that get executed after all the built in middlewares are executed.

Leave a Reply

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