Middleware in ASP.NET Core

Middleware is a small component that handles requests and responses and the Series of Middleware together forms a pipeline.

When you send a request to ASP.NET Core Application, it passes through a pipeline, and it is handled by appropriate Middleware.

There are various predefine middleware exits such

  1. UseStaticFiles
  2. UseRouting
  3. UseAuthentication
  4. UseAuthorization
  5. UseSession
  6. UseCors

You can also write your own Middleware. The order of middleware configured is important they will execute as you have configured it in Startup configure method.

In the above image, you can see how incoming request is passed through middleware’s and in same way response is passed in reverse order through all middleware’s.

There are four types of method to configure middleware.

Run: – Run delegate terminates the pipeline

Use: – it handles the request or passes the request to next delegate

Map: – Branches the request pipeline based on matches of the given request path. If the request path starts with the given path, the branch is executed.

MapWhen: – Branches the request pipeline based on the result of the given predicate.

For showing Demo, I have created an ASP.NET Core Application with name ‘WebMiddleware‘.

Run
Run Middleware terminates the pipeline this middleware handles all request.
Any middleware called after Run middleware doesn’t execute.
Run Middleware cannot pass the request to the next component.
In this code, we are going to write Message to response object as shown below.

Code Snippet

app.Run(async (context) =>
{
    await context.Response.WriteAsync("Hi I am 'Run' Middleware Response (..)");
});

Now we have added two Run methods in Configure method it must display to message in the browser.
But it will only display one Message because it cannot pass the request to the next component.

Use

Use Middleware handles the request or passes the request to the next delegate.

In Use middleware, you can execute logic and then call ‘next.Invoke()‘ to call next middleware component.
If you see below image, you will get a clear idea how to Use middleware works.

Code Snippet

app.Use(async (context, next) =>
{
    // Do work that doesn't write to the Response.
    await context.Response.WriteAsync("First Call   ---> ");

    await next.Invoke();
    // Do logging or other work that doesn't write to the Response.
    await context.Response.WriteAsync("Second Call  ---> ");
});

In the above code snippet in Use Middleware, we can perform some logic in Use middleware and then call ‘next.Invoke()‘ to call next middleware which is RUN this middleware, RUN middleware will terminate pipeline it will not call later middleware. It will start to execute in reverse order it will execute Use middleware and write Response.

If you see below output, then you will get an idea of how it works.

Map

Map Method Branches the request pipeline based on matches of the given request path. If the request path starts with the given path, the branch is executed.

Referenced from:- https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.builder.iapplicationbuilder?view=aspnetcore-3.0

The Map method takes a delegate, and within the delegate, it allows to use both Run and Use according to the requirement.

Code Snippet

app.Map("/demo", (appBuilder) =>
{
    appBuilder.Use(async (context, next) =>
    {
        // Do work that doesn't write to the Response.
        await context.Response.WriteAsync("First Call   ---> ");

        await next.Invoke();
        // Do logging or other work that doesn't write to the Response.
        await context.Response.WriteAsync("Second Call  ---> ");
    });

    appBuilder.Run(async (context) =>
    {
        await context.Response.WriteAsync("Hi I am 'Run' Middleware Response (..)  ---> ");
    });
});

Inside Map extension method we have written two delegates one is Use, and another one is Run Map extension method will get triggered when user will call ‘/demo‘ path.

MapWhen

MapWhen method Branches the request pipeline based on the result of the given predicate.

If we want to execute middleware based on the query string or cookie, headers then we can use MapWhen extension.

Code Snippet

app.MapWhen(context => context.Request.Query.ContainsKey("pincode"), (appBuilder) =>
{
    appBuilder.Use(async (context, next) =>
    {
        // Do work that doesn't write to the Response.
        await context.Response.WriteAsync("First Call   ---> ");
        await next.Invoke();
    });

    appBuilder.Run(async (context) =>
    {
        var pincode = context.Request.Query["pincode"];
        await context.Response.WriteAsync($"PinCode used = {pincode}");
    });
});

In the above code, we look for ‘pincode‘ string in URL if it exists then MapWhen method will execute inside this extension we can use other delegates such as RUN and USE.

By Saineshwar Bageri

I am Microsoft MVP | C# Corner MVP | Code Project MVP | FULL STACK .NET Developer and working on .Net Web Technology (Asp.net, Asp.net Core,.Net Core, C#, Sqlserver, MVC, Windows, Console Application, javascript, jquery, json, ORM Dapper) and also a freelance developer.