Introduction
In modern web applications built using ASP.NET Core Web API, handling requests and responses efficiently is very important. Every request that comes to your application passes through a pipeline before reaching the controller and then goes back through the same pipeline as a response.
This pipeline is called the Middleware Pipeline.
Sometimes, built-in middleware is not enough, and you need custom logic like:
Logging requests
Handling exceptions
Validating headers
Modifying responses
This is where Custom Middleware in ASP.NET Core becomes very useful.
In this article, we will learn how to create custom middleware in ASP.NET Core step by step in simple words, with real-world examples and best practices.
What is Middleware in ASP.NET Core?
Middleware is a component that handles HTTP requests and responses.
👉 It sits in the request pipeline and can:
Process incoming requests
Modify request/response
Call the next middleware
Stop the request if needed
Simple Flow
Request → Middleware 1 → Middleware 2 → Controller → Middleware → Response
👉 Each middleware decides whether to pass control to the next middleware.
Why Use Custom Middleware?
Sometimes you need logic that is not available by default.
1. Logging Requests and Responses
You can track every request coming into your API.
2. Global Exception Handling
Handle errors in one place instead of repeating try-catch everywhere.
3. Authentication or Header Validation
Check tokens or headers before processing the request.
4. Performance Monitoring
Measure how long each request takes.
👉 Custom middleware helps keep your code clean and reusable.
Types of Middleware in ASP.NET Core
1. Built-in Middleware
Examples:
UseRouting
UseAuthentication
UseAuthorization
2. Custom Middleware
Middleware created by developers to handle specific logic.
How to Create Custom Middleware in ASP.NET Core
Let’s implement a custom middleware step by step.
Step 1: Create Middleware Class
Create a new 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}");
}
}
Explanation
RequestDelegate → Represents the next middleware
InvokeAsync → Main method executed for every request
HttpContext → Contains request and response data
👉 Always call _next(context) to continue the pipeline.
Join the conversation! Your thoughts help the community grow.