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