Introduction
Middleware components are one of the most important concepts in ASP.NET Core Web API development. They control how requests and responses flow through your application.
If you understand middleware properly, you can build powerful features like authentication, logging, exception handling, routing, and much more.
In this article, you will learn what middleware is, how it works internally, and how to create your own middleware step by step using simple language and real examples.
What is Middleware in ASP.NET Core?
Middleware is a piece of code that handles HTTP requests and responses.
It sits in the request pipeline and decides:
Whether to process the request
Whether to pass it to the next component
Whether to stop the request
In simple words:
Middleware = Request + Processing + Response
Understanding the Request Pipeline
ASP.NET Core uses a pipeline where multiple middleware components are executed in sequence.
Flow:
Request comes from client
Passes through multiple middleware
Each middleware can modify request/response
Finally reaches endpoint (controller)
Response travels back through same middleware
Example flow:
Client → Middleware 1 → Middleware 2 → Middleware 3 → Controller → Response → Middleware 3 → Middleware 2 → Middleware 1 → Client
This is also called a "chain of responsibility" pattern.
How Middleware Works Internally
Each middleware has access to:
Basic structure:
public async Task InvokeAsync(HttpContext context)
{
// Before next middleware
await _next(context);
// After next middleware
}
Key idea:
Built-in Middleware in ASP.NET Core
ASP.NET Core provides many built-in middleware components:
UseRouting → Matches request to endpoints
UseAuthentication → Validates user identity
UseAuthorization → Checks permissions
UseStaticFiles → Serves static content
UseExceptionHandler → Handles global exceptions
UseHttpsRedirection → Redirects HTTP to HTTPS
Example configuration:
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.UseRouting();
app.MapControllers();
Order matters here. Changing order can break your application.
Why Middleware Order is Important
Middleware executes in the order it is added.
Example:
app.UseAuthentication();
app.UseAuthorization();
If reversed:
app.UseAuthorization();
app.UseAuthentication();
Authorization will fail because user is not authenticated yet.
So always maintain correct order.
Types of Middleware
There are three common ways to create middleware:
1. Inline Middleware
Defined directly in Program.cs
app.Use(async (context, next) =>
{
Console.WriteLine("Request started");
await next();
Console.WriteLine("Response finished");
});
2. Convention-based Middleware
Custom class with Invoke or InvokeAsync method
public class LoggingMiddleware
{
private readonly RequestDelegate _next;
public LoggingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
Console.WriteLine("Request incoming");
await _next(context);
Console.WriteLine("Response outgoing");
}
}
Register it:
app.UseMiddleware<LoggingMiddleware>();
3. Factory-based Middleware
Uses IMiddleware interface (less common but useful with DI)
public class CustomMiddleware : IMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
await next(context);
}
}
Register:
builder.Services.AddTransient<CustomMiddleware>();
app.UseMiddleware<CustomMiddleware>();
Creating Custom Middleware Step by Step
Let’s create a simple request logging middleware.
Step 1: Create Middleware Class
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);
Console.WriteLine($"Response Status: {context.Response.StatusCode}");
}
}
Step 2: Register Middleware
app.UseMiddleware<RequestLoggingMiddleware>();
Step 3: Test
Run API and hit any endpoint. You will see logs in console.
Short-Circuiting Middleware
Middleware can stop request pipeline.
Example:
app.Use(async (context, next) =>
{
if (!context.Request.Headers.ContainsKey("Authorization"))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Unauthorized");
return;
}
await next();
});
Here request stops if header is missing.
Middleware vs Filters in ASP.NET Core
| Feature | Middleware | Filters |
|---|
| Scope | Global | MVC only |
| Execution | Before MVC | Inside MVC |
| Use case | Logging, Auth | Action-specific logic |
Real-World Use Cases of Middleware
Middleware is used in:
Best Practices for Middleware
Common Mistakes to Avoid
Summary
Middleware in ASP.NET Core is a powerful concept that controls how HTTP requests and responses are handled. By understanding the request pipeline, middleware order, and how to build custom middleware, you can create scalable and maintainable web applications. Proper use of middleware improves performance, security, and overall application design.