
Types of Middleware in ASP.NET
Author - Abdul Rahman (Bhai)
Middleware
2 Articles
Table of Contents
What we gonna do?
In this article, let's learn about different types of Middleware in ASP.NET.
Note: If you have not done so already, I recommend you read the article on Introducing Middleware in ASP.NET.
Middleware's are C# classes and logics connected by chain of responsibility pattern to handle and terminate request pipeline in the order of appearance. Middleware's are configured by default in Program.cs and the order in which they run are important. Request's are processed from top to bottom and outside to inside and back again. These are created once in application start up.
There are 5 types of middleware:
- Run Middleware
- Use Middleware
- UseWhen Middleware
- Map Middleware
- MapWhen Middleware

Why we gonna do?
Different middleware types give you precise control over how and when the request pipeline is modified. Using the wrong type can lead to requests not being handled correctly — for example, accidentally short-circuiting requests that should continue, or failing to rejoin the main pipeline after a branch.
Understanding the five types — Run, Use, UseWhen, Map, and MapWhen — lets you build pipelines that are both efficient and correct, applying logic only where it is needed.
How we gonna do?
Run Middleware
Run Middleware execute the delegate and terminates processing the request pipeline. Run delegates don't receive a next parameter. The first Run delegate is always terminal and terminates the pipeline. Run should always be the last one in pipeline.
The simplest possible ASP.NET Core app sets up a single request delegate that handles all requests. This case doesn't include an actual request pipeline. Instead, a single anonymous function is called in response to every HTTP request.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from Run Middleware!");
});
app.Run();
Use Middleware
Use Middleware execute the delegate and proceed to next in request pipeline. We can chain multiple request delegates together with Use. The next parameter represents the next delegate in the pipeline. You can short-circuit the pipeline by not calling the next parameter. You can typically perform actions both before and after the next delegate.
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Hello from Use Middleware!");
await next();
await context.Response.WriteAsync("Bye from Use Middleware!");
});
When a delegate doesn't pass a request to the next delegate, it's called short-circuiting the request pipeline. Short-circuiting is often desirable because it avoids unnecessary work. For example, Static File Middleware can act as a terminal middleware by processing a request for a static file and short-circuiting the rest of the pipeline.
UseWhen Middleware
UseWhen Middleware branches the request pipeline based on the result of the given predicate and this branch is rejoined to the main pipeline if it doesn't short-circuit or contain a terminal middleware.
app.UseWhen(context => context.Request.Query.ContainsKey("branch"),
appBuilder => HandleBranchAndRejoin(appBuilder));
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate!");
});
void HandleBranchAndRejoin(IApplicationBuilder app)
{
var logger = app.ApplicationServices.GetRequiredService<ILogger<Program>>();
app.Use(async (context, next) =>
{
var branchVer = context.Request.Query["branch"];
logger.LogInformation("Branch used = {branchVer}", branchVer);
// Do work that doesn't write to the Response.
await next();
// Do other work that doesn't write to the Response.
});
}
Map Middleware
Map Middleware conditionally execute a method and does not return to request pipeline. Map extensions are used as a convention for branching the pipeline. Map branches the request pipeline based on matches of the given request path. If the request path starts with the given path, the branch is executed.
app.Map("/branch", HandleBranch);
private static void HandleBranch(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Hello from inside Map Use Middleware!");
await next();
await context.Response.WriteAsync("Bye from inside Map Use Middleware!");
});
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello from inside Map Run Middleware!");
});
}
MapWhen Middleware
MapWhen branches the request pipeline based on the result of the given predicate. Any predicate of type Func<HttpContext, bool> can be used to map requests to a new branch of the pipeline. Unlike with UseWhen, this branch is not rejoined to the main pipeline.
app.MapWhen(context => context.Request.Query.ContainsKey("query"), context =>
{
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello from inside MapWhen Middleware!");
});
});
Summary
In this article, we learn't different types Middleware in ASP.NET and how it processes the request pipeline and how we can use middleware to customise the HTTP request. In next article let's learn about the unit testing middleware in ASP.NET.