π 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:
- Inspect or modify the incoming request.
- Call the next middleware in the pipeline.
- 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
Post a Comment