πŸ”„ Understanding Middleware in ASP.NET Core: The Pipeline Powerhouse

 

One of the key reasons ASP.NET Core is so flexible and fast is its middleware pipeline. Middleware components are the building blocks of request/response processing. If you’ve ever used app.UseRouting() or app.UseAuthentication(), you’ve already worked with middleware.

In this post, you’ll learn:

  • What middleware is
  • How the middleware pipeline works
  • Common built-in middleware
  • How to write custom middleware

🧠 What Is Middleware?

In ASP.NET Core, middleware is software that's assembled into an application pipeline to handle requests and responses. Each middleware can:

  1. Inspect or modify the incoming request.
  2. Call the next middleware in the pipeline.
  3. Handle the response before or after the next middleware runs.

Think of it like a series of gates where each gate can check, modify, or stop the HTTP request as it moves toward the final endpoint.


πŸ” The Middleware Pipeline

The order of middleware is crucial. Requests flow top-down and responses flow bottom-up.

csharp


public void Configure(IApplicationBuilder app)

{

    app.UseMiddleware<LoggingMiddleware>();  // 1

    app.UseAuthentication();                 // 2

    app.UseRouting();                        // 3

    app.UseAuthorization();                  // 4

    app.UseEndpoints(endpoints =>            // 5

    {

        endpoints.MapControllers();

    });

}


🧱 Built-in Middleware Examples

Middleware

Purpose

UseRouting

Matches request to route

UseAuthorization

Enforces policies and roles

UseAuthentication

Validates credentials (cookies, JWTs)

UseCors

Cross-origin resource sharing rules

UseStaticFiles

Serves static files like JS/CSS

UseExceptionHandler

Global error handling


✍️ Creating Custom Middleware

Let’s walk through building a simple Request Logging Middleware.

Step 1: Create the Middleware Class

csharp


public class RequestLoggingMiddleware

{

    private readonly RequestDelegate _next;

 

    public RequestLoggingMiddleware(RequestDelegate next)

    {

        _next = next;

    }

 

    public async Task InvokeAsync(HttpContext context)

    {

        Console.WriteLine($"[Request] {context.Request.Method} {context.Request.Path}");

       

        await _next(context); // Call the next middleware

       

        Console.WriteLine($"[Response] Status Code: {context.Response.StatusCode}");

    }

}


Step 2: Register the Middleware in Program.cs

csharp


app.UseMiddleware<RequestLoggingMiddleware>();

Alternatively, you can create a nice extension method:

csharp


public static class MiddlewareExtensions

{

    public static IApplicationBuilder UseRequestLogging(this IApplicationBuilder app)

    {

        return app.UseMiddleware<RequestLoggingMiddleware>();

    }

}

Then call:

csharp


app.UseRequestLogging();


🧠 Use Cases for Custom Middleware

Use Case

Description

Logging

Log requests, headers, or responses

Exception Handling

Catch and format all unhandled exceptions

Localization

Set culture from query string or headers

Security

Custom authentication logic

Caching

Set cache headers conditionally


⚠️ Middleware Best Practices

  • Keep it focused — one responsibility per middleware.
  • Always call _next(context) unless you intend to short-circuit.
  • Add middleware in the correct order.
  • Use try/catch if wrapping logic to avoid breaking the pipeline.
  • Middleware should be stateless and thread-safe.

πŸ§ͺ Bonus: Middleware That Blocks Suspicious IPs

csharp


public class BlockIpMiddleware

{

    private readonly RequestDelegate _next;

    private readonly List<string> _blockedIps = new() { "192.168.1.10" };

 

    public BlockIpMiddleware(RequestDelegate next)

    {

        _next = next;

    }

 

    public async Task InvokeAsync(HttpContext context)

    {

        var remoteIp = context.Connection.RemoteIpAddress?.ToString();

        if (_blockedIps.Contains(remoteIp))

        {

            context.Response.StatusCode = 403;

            await context.Response.WriteAsync("Forbidden");

            return;

        }

 

        await _next(context);

    }

}


πŸ“¦ Summary

Middleware is at the heart of ASP.NET Core’s request pipeline. Understanding how to use and build it enables you to:

Intercept and manipulate requests/responses
Centralize cross-cutting concerns
Build modular and testable applications

 

Comments

Popular posts from this blog

Scrutor the built-in Dependency Injection (DI)

πŸ§… Understanding the Onion Architecture: A Clean Approach to Building Scalable Applications

πŸ”Œ Extension Methods in C#: Power Up Your Code Without Modifying It

Understanding Dependency Injection: A Modern Guide for Developers

🌐 CORS in .NET Explained: Solving the Cross-Origin Problem Like a Pro

πŸ” JWT (JSON Web Token) Explained: Secure Your APIs the Modern Way

πŸ—‚️ DROP vs DELETE vs TRUNCATE in SQL: What’s the Difference?

Ensuring Data Integrity: The Backbone of Reliable Systems

πŸ”— SQL JOINs Explained: Mastering Table Relationships

πŸ›‘️ SIEM Logs Explained: How to Build Secure and Auditable .NET Apps