Create Middleware in dotnet

dotnet middleware

Create Middleware in dotnet

What is middleware in ASP.NET

  • A request received to a ASP.NET web application is encapsulated as a HttpContext object and the object is processed by a series of application logic (aka middleware) in a configured sequence.
  • This sequence of middleware in which the requst is processed is called Request Pipeline

image.png

Use, Map, Run methods

  • Use, Map and Run methods help us to configure the middleware pipeline in an ASP.NET Core application
  • Use method appends a new middleware to the middleware pipeline
// Use Middleware: Append middleware to pipeline
app.Use(async (context, next) =>
{
    Console.WriteLine("Executing middleware before next()");
    await next.Invoke();  // Calling the next middleware in the pipeline
    Console.WriteLine("Executing middleware after next()");
});

  • Map method branches the middleware pipeline for a specific request path
// Map Middleware: split middleware pipeline for a specific route
app.Map("/admin", adminApp =>
{
    adminApp.Use(async (context, next) =>
    {
        Console.WriteLine("Admin Area Middleware: Before next()");
        await next();
        Console.WriteLine("Admin Area Middleware: After next()");
    });

    adminApp.Run(async context =>
    {
        await context.Response.WriteAsync("Welcome to the Admin Dashboard!\\n");
    });
});

  • Run method terminates the middleware pipeline

    // Run Middleware: terminates the middleware pipeline
    app.Run(async context =>
    {
        await context.Response.WriteAsync("From app.Run method");
    });
    
    

Create a Middleware class by implementing IMiddleware

  • A middleware class can be created as shown below. It should extend the IMiddleware interface
public class CustomMiddleware(ILogger<CustomMiddleware> logger) : IMiddleware
{
    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        logger.LogInformation("Before request from custom middleware");
        await next(context);
        logger.LogInformation("After request from custom middleware");
    }
}

  • Requested Dependencies can be injected in the constructor
  • The middleware should be registered in the dependency container as shown below
builder.Services.AddTransient<CustomMiddleware>();

  • After registering the middleware, it can be addin the middleware pipeline as shown below
app.UseMiddleware<CustomMiddleware>();

  • Extension methods can be created to make middleware registering and middleware usage more readable as shown below
public static class CustomMiddleExtensions
{
    public static IApplicationBuilder UseCustomMiddleware(this IApplicationBuilder app)
        => app.UseMiddleware<CustomMiddleware>();
    public static IServiceCollection AddCustomMiddleware(this IServiceCollection services){
	    services.AddTransient<CustomMiddleware>();
	    return services;
    }
} 

  • Now middleware can be registered using builder.Services.AddCustomMiddleware() and middleware can be added to middleware pipeline using app.UseCustomMiddleware()
  • A middleware class can be created as shown below. The class should have
    • RequestDelegate in the constructor
    • public async Task InvokeAsync(HttpContext context) method in class
    • await next(context) should be called inside the InvokeAsync method
public class CustomMiddleware(RequestDelegate next)
{
    public async Task InvokeAsync(HttpContext context, ILogger<CustomMiddleware> logger)
    {
        logger.LogInformation("Before request from CustomMiddleware");
        await next(context);
        logger.LogInformation("After request from CustomMiddleware");
    }
}

  • The middleware should be added to request pipeline using the following
app.UseMiddleware<CustomMiddleware>();

  • This style of creating a middleware class is not recommended since the arguments of InvokeAsync changes with injecting dependencies.

References

Comments

Popular posts from this blog

ClaimsPrincipal, ClaimsIdentity, Claims explained in dotnet authentication

Manage packages in dotnet applications

Implicit usings, top level statements, file scoped namespaces in dotnet