Creating Custom Middleware in ASP.Net Core

Middleware is a software that's assembled into an app pipeline to handle requests and responses. Each component:

  • Chooses whether to pass the request to the next component in the pipeline.
  • Can perform work before and after the next component in the pipeline.

Request delegates are used to build the request pipeline and are configured using Run , Map and Use extension methods.

The ASP.Net Core request pipeline consists of a sequence of request delegates, called one after the other. The following diagram from Microsoft docs demonstrates the concept. The thread of execution follows the black arrows.

image.png

Create custom middleware

Lets consider the following middleware example configured in the Startup.cs which sets the culture for the current request from Claims of HttpContext.

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Use(async (context, next) =>
        {
           var claims = context?.User?.Claims?.ToList();

            // Get cultureId out of claims.
            // If not set then fallback to en-US
            var cultureId = claims.
                ?FirstOrDefault(claim => claim.Type == "CultureId")
                ?.Value 
            ?? "en-US";

            // Retrieve a read-only instance of culture
            // using the specified culture name
            var cultureInfo = CultureInfo.GetCultureInfo(cultureId);

            CultureInfo.CurrentCulture = cultureInfo;
            CultureInfo.CurrentUICulture = cultureInfo;

            // Call the next delegate/middleware in the pipeline
            await next();
        });
    }
}

Now we can extract the above middleware delegate into a class. Our middleware class must include:

  • A public constructor with a parameter of type RequestDelegate
  • A public method named Invoke or InvokeAsync. This method must return a Task accept a first parameter of type HttpContext
public class TokenCultureMiddleware
{
    private readonly RequestDelegate _next;

    public TokenCultureMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var claims = context?.User?.Claims?.ToList();

        // Get cultureId out of claims.
        // If not set then fallback to en-US
        var cultureId = claims.
            ?FirstOrDefault(claim => claim.Type == "CultureId")
            ?.Value 
        ?? "en-US";

        // Retrieve a read-only instance of culture
        // using the specified culture name
        var cultureInfo = CultureInfo.GetCultureInfo(cultureId);

        CultureInfo.CurrentCulture = cultureInfo;
        CultureInfo.CurrentUICulture = cultureInfo;

        // Call the next delegate/middleware in the pipeline
        await _next.Invoke(context);
    }
}

Middleware extension method

Last we can create a middleware extension method and call our custom middleware from Startup.Configure

public static class TokenCultureMiddlewareExtensions
{
    public static IApplicationBuilder UseTokenCulture(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<TokenCultureMiddleware>();
    }
}

And in Startup.Configure

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        // Call our extension method
        app.UseTokenCulture();
    }
}

Did you find this article valuable?

Support Theodoros Karropoulos by becoming a sponsor. Any amount is appreciated!