Understanding Middleware in ASP.NET Core

In this article, we will explain the features and concepts of Middleware in ASP.NET Core. At the end of this article you will get a clear understanding of the following meanings:

  • What is Middleware?  
  • Why is Middleware sorting important?  
  •  Understand how to run, use and Map Method How to build a custom middleware?  
  • Directory How can directory browsing be enabled by Middleware?

What is Middleware?

Middleware is a piece of code in the application pipeline that is used to control requests and responses.

For example, we might have a middleware to verify a user, a middleware to check for errors, and another middleware to use static files such as JavaScript files, CSS files, images, and so on.

Middleware can be embedded as part of the .NET Core framework, which is added via NuGet packages, or it can be custom middleware. These middleware components are configured as part of the program startup class in the configure method. Configure methods configure a pipeline processing request for an ASP.NET Core application that includes a string of delegate requests that are executed one after the other.

The image below shows how to process a request through middleware components.


In general, each middleware may control incoming requests and pass the execution to the next middleware for further processing.

But a middleware can decide not to call the next piece of middleware in the pipeline. It is called short-circuiting or terminate the request pipeline.

Let's create an ASP.NET Core Web application and see the default middleware configuration in the Startup class Configure method.

  1. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)      
  2.     {      
  3.         if (env.IsDevelopment())      
  4.         {      
  5.             //This middleware is used reports app runtime errors in development environment.    
  6.             app.UseDeveloperExceptionPage();      
  7.         }      
  8.         else      
  9.         {      
  10.             //This middleware is catches exceptions thrown in production environment.     
  11.             app.UseExceptionHandler("/Error");     
  12.             // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.      
  13.             app.UseHsts(); //adds the Strict-Transport-Security header.      
  14.         }      
  15.         //This middleware is used to redirects HTTP requests to HTTPS.    
  16.         app.UseHttpsRedirection();     
  17.           
  18.         //This middleware is used to returns static files and short-circuits further request processing.     
  19.         app.UseStaticFiles();    
  20.           
  21.         //This middleware is used to route requests.     
  22.         app.UseRouting();     
  23.           
  24.         //This middleware is used to authorizes a user to access secure resources.    
  25.         app.UseAuthorization();      
  26.           
  27.         //This middleware is used to add Razor Pages endpoints to the request pipeline.      
  28.         app.UseEndpoints(endpoints =>      
  29.         {      
  30.             endpoints.MapRazorPages();                 
  31.         });      
  32.     }   

The ASP.NET Core framework provides some built-in middleware components that we can easily use in the Configure method.

Middleware arrangement

The middleware components are executed in the order added to the pipeline, and care must be taken that the middleware is added in the correct order, otherwise the program may not work as expected. This arrangement is very important for security, efficiency and performance.

The following middleware components are recommended for common application scenarios, respectively:


The first configured middleware receives the request, modifies it (if necessary), and transfers control to the next firmware. Similarly, if the response is processed, if the echo returns to the bottom of the tube, the first middleware will run in the last step. This is why Exception-handling delegates are called early in the pipeline, so they can validate the result and show a possible exception in a browser-friendly way.

Understand how to run, use and Map Method

App.Run()

This middleware component is able to show the Run [Middleware] methods running at the end of the pipeline. Generally, it acts as a middleware terminal and a request pipeline is added at the end of the request processing process because it cannot call the next middleware.

App.Use()

app.Use() is used to configure multiple middleware. Unlike app.Run (), we can put the next parameter in it, which calls the next delegate request in the pipeline. We can also terminate the pipeline by not calling the next parameter.

Check the following example with app.Use () and app.Run () and also see output / response:


  1. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)      
  2.     {      
  3.         app.Use(async (context, next) =>      
  4.         {      
  5.             await context.Response.WriteAsync("Before Invoke from 1st app.Use()\n");      
  6.             await next();      
  7.             await context.Response.WriteAsync("After Invoke from 1st app.Use()\n");      
  8.         });      
  9.           
  10.         app.Use(async (context, next) =>      
  11.         {      
  12.             await context.Response.WriteAsync("Before Invoke from 2nd app.Use()\n");      
  13.             await next();      
  14.             await context.Response.WriteAsync("After Invoke from 2nd app.Use()\n");      
  15.         });      
  16.           
  17.         app.Run(async (context) =>      
  18.         {      
  19.             await context.Response.WriteAsync("Hello from 1st app.Run()\n");      
  20.         });      
  21.           
  22.         // the following will never be executed      
  23.         app.Run(async (context) =>      
  24.         {      
  25.             await context.Response.WriteAsync("Hello from 2nd app.Run()\n");      
  26.         });      
  27.     }      


The first app.Run () terminates the pipeline. In this example, only the first delegate ("Hello from 1st app.Run ()") is executed and the request never reaches the second run method.

App.Map()

These extensions are used as a contract for a pipeline multi-line system. map Expands the request processing process based on the request path. If the request path starts with the given path, a new branch of middleware will run. In fact, you can divide the request processing process into several branches, each of which may run depending on the request path.

Check the following example with app.Map () and also see output / response:


  1. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)    
  2.    {    
  3.        app.Map("/m1", HandleMapOne);    
  4.        app.Map("/m2", appMap => {    
  5.            appMap.Run(async context =>    
  6.            {    
  7.                await context.Response.WriteAsync("Hello from 2nd app.Map()");    
  8.            });    
  9.        });    
  10.        app.Run(async (context) =>    
  11.        {    
  12.            await context.Response.WriteAsync("Hello from app.Run()");    
  13.        });    
  14.    }    
  15.    private static void HandleMapOne(IApplicationBuilder app)    
  16.    {    
  17.        app.Run(async context =>    
  18.        {    
  19.            await context.Response.WriteAsync("Hello from 1st app.Map()");    
  20.        });     
  21.    }    

The table below shows localhost requests and responses using the code above.

ResponseRequest
()Hello from app.Runhttps://localhost:44362/
()Hello from 1st app.Maphttps://localhost:44362/m1
()Hello from 1st app.Maphttps://localhost:44362/m1/xyz
()Hello from 2nd app.Maphttps://localhost:44362/m2
()Hello from app.Runhttps://localhost:44362/m500
Build a custom middleware

Middleware is generally encapsulated in a class and exposed with the method extension. Custom middleware can be created with a class by the InvokeAsync () method and the RequestDelegate type parameter in the constructor. In order to run the next middleware in a row, the RequestDelegate type is required.

Let's consider an example where we need to create custom middleware to register a URL request in a web application.


  1. public class LogURLMiddleware    
  2.     {    
  3.         private readonly RequestDelegate _next;    
  4.         private readonly ILogger<LogURLMiddleware> _logger;    
  5.         public LogURLMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)    
  6.         {    
  7.             _next = next;    
  8.             _logger = loggerFactory?.CreateLogger<LogURLMiddleware>() ??    
  9.             throw new ArgumentNullException(nameof(loggerFactory));    
  10.         }    
  11.         public async Task InvokeAsync(HttpContext context)    
  12.         {    
  13.             _logger.LogInformation($"Request URL: {Microsoft.AspNetCore.Http.Extensions.UriHelper.GetDisplayUrl(context.Request)}");    
  14.             await this._next(context);    
  15.         }  
  16.     }  

  1. public static class LogURLMiddlewareExtensions    
  2. {    
  3.     public static IApplicationBuilder UseLogUrl(this IApplicationBuilder app)    
  4.     {    
  5.         return app.UseMiddleware<LogURLMiddleware>();    
  6.     }    
  7. }    

In the configure method:

  1. app.UseLogUrl();    

Enable directory browsing with middleware

Directory browsing allows users of your web application to browse directory directories and files in a specific directory.

directory browsing is disabled by default for security reasons.

Let's consider an example where we want to accept a list of images in the browser under the images folder at wwwroot. UseDirectoryBrowser can control and submit those images to that request, and then short-circuit the rest of the pipeline.

  1. app.UseDirectoryBrowser(new DirectoryBrowserOptions    
  2.     {    
  3.         FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot""images")),    
  4.         RequestPath = "/images"    
  5.     });    

Summary

So the middleware in ASP.NET Core controls how our application responds to HTTP requests.

In summary, each middleware component in ASP.NET Core:

  • It has access to both incoming and outgoing requests.
  • It may just move the request to the next part of the middleware in the pipeline.
  • It may do some processing logic and then pass this request to the next middleware for further processing.
  • It may terminate the request processing process (short circuit) whenever necessary.
  • Runs in the order added to the pipeline.




User:sinahabibi
12/12/2020
Visit:66
Asp.Net

How to use Middleware what is Middleware working with Middleware in core applications how to run Middleware customizing Middleware familiarity with Middleware how to implement Middleware in core working with Middleware in asp.net core
You must be logged in to post a comment