Monday, February 11, 2019

Middleware in ASP.NET Core

Middleware is the software component that is assembled into an application HTTP pipeline to handle requests and responses
  • Here, the Software component means the class which is executed on every request in ASP.NET Core application.
  • Typically, there will be multiple middleware in ASP.NET Core web application 
  • It can be either framework provided(built-in) Middleware, added via NuGet or your own custom middleware
The following figure illustrates the execution of middleware components:
Components in Middleware:
  • Chooses whether to pass the request to the next component in the pipeline.
  • Can perform work before and after the next component is invoked in the pipeline.

Configure Middleware


We can configure middleware in the Configure method of the Startup class using IApplicationBuilder instance.


  • In the above example, Run() is an extension method on IApplicationBuilder instance which adds a terminal middleware to the application's request pipeline
  • Request delegates are configured using RunMap, and Use extension methods

Run() extension method

  • At this point you might be worried about Run() method. So let me explain about the Run() method:
  • The Run method is an extension method on IApplicationBuilder and accepts a parameter of RequestDelegate
  • The signature of Run() method is,
public static void Run (this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Http.RequestDelegate handler);

  • Request delegates are used to build the request pipeline, and are configured using Run, Map and Use Extension methods
  • The Request delegate handle each HTTP request
  • The signature of RequestDelegate is,
public delegate System.Threading.Tasks.Task RequestDelegate(HttpContext context);

  • Since the RequestDelegate is the parameter of Run() method, it should accept the HttpContext parameter and return Task
  • You can either specify a lambda expression or specify a function in the Run method  as shown in figure below:
  • the above examples of configuring middleware using Run() method, both code snippet in above figure are equivalent

Use() extension method

  • We can use multiple request delegates together with Use() extension method 
  • It is similar to Run() method except that it includes next parameter. Consider the following example:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.Use(async (context, next) =>
    {
        await context.Response.WriteAsync("This is from first Middleware!");

        await next();
    });

    app.Run(async (context) =>
    {
        await context.Response.WriteAsync("This is from second Middleware"); 
    });
}
  • When you run the above code, then it will display the following output on your browser:
  • The next parameter represents the next delegate in the pipeline. 
  • The middleware components can be used for following app scenarios:
    • Exception/error handling
    • HTTP Strict Transport Security Protocol
    • HTTPS redirection
    • Static file server
    • Cookie policy enforcement
    • Authentication
    • Session
    • MVC

public void Configure(IApplicationBuilder app) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); //Middleware } else { app.UseExceptionHandler("/Error"); //Middleware } app.UseHttpsRedirection(); //Middleware app.UseStaticFiles(); //Middleware app.UseCookiePolicy(); //Middleware app.UseAuthentication(); //Middleware app.UseSession(); //Middleware app.UseMvc(); //Middleware }
  • The order that middleware components added in the Configure method defines the order in which the middleware components are invoked on requests and the reverse order for the response

Map() extension method

  • Map extensions are used for branching the pipeline
  • Map branches the request pipeline based on given request path
  • If the request path starts with the given path, the branch is executed

public class Startup { private static void MapRouteOne(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync("Map Route One"); }); } private static void MapRouteTwo(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync("Map Route Two"); }); } public void Configure(IApplicationBuilder app) { app.Map("/mapone", MapRouteOne); app.Map("/maptwo", MapRouteTwo); app.Run(async context => { await context.Response.WriteAsync("Hello World"); }); } }
The following figures shows the output of above example, at different map path.







No comments:

Post a Comment