TL;DR
Use
adds middleware that can process and pass requests along the pipeline.Run
is terminal middleware, once hit, the pipeline ends and no further middleware executes.Map
branches the pipeline by path, creating sub-pipelines for specific routes.- Always call
next()
inUse
unless you want to short-circuit the pipeline. - Middleware order and correct usage of
Use
,Run
, andMap
are key to building robust ASP.NET Core APIs.
Hey everyone! If you’ve ever worked with ASP.NET Core, you know middleware is the backbone of how requests are handled. But getting the pipeline flow right can be tricky. Getting Use
, Run
, and Map
mixed up can lead to middleware that doesn’t fire or, worse, short-circuits your entire request.
Let’s quickly break down the difference.
Use
: The Pipeline Link
Think of Use
as a link in a chain or a toll booth on a highway. Its job is to perform an action and then pass the request to the next component in the pipeline. If you don’t call next()
, the chain breaks, and the request stops.
You’ll use this for tasks that need to inspect or modify a request and then let it continue, like logging, authentication, or adding response headers.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// This middleware logs the request path and passes it on.
app.Use(async (context, next) =>
{
Console.WriteLine($"[Use] Handling request for: {context.Request.Path}");
// Calls the next middleware in the pipeline.
await next(context);
});
app.MapGet("/", () => "Hello from the main pipeline!");
app.Run();
Notice how await next(context)
is the key. It’s what keeps the request moving down the line.
Run
: The End of the Line
Run
is a terminal middleware. It’s a dead-end road. Once a request hits a Run
delegate, the pipeline stops. There’s no next
parameter because it’s not meant to call anything after it.
Run
is perfect for handling a request that should be fully handled by one piece of middleware, like a simple health check endpoint or a fallback “not found” response.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// This middleware will ALWAYS run and terminate the request.
// Anything registered after this won't be called.
app.Run(async context =>
{
Console.WriteLine("[Run] Pipeline ends here.");
await context.Response.WriteAsync("This is the end of the pipeline.");
});
// This will never be reached.
app.MapGet("/", () => "You will never see this!");
app.Run();
Map
: The Fork in the Road
Map
is how you create a branch in your pipeline. Think of it as a fork in the road that directs traffic based on the request path. If a request path starts with the value you specify, it gets diverted into a separate, isolated sub-pipeline.
This is incredibly useful for creating path-specific middleware chains, like one for /api
and another for /admin
.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// This branch is only taken if the path starts with /hello
app.Map("/hello", branchApp =>
{
// This sub-pipeline has its own terminal middleware.
branchApp.Run(async context =>
{
await context.Response.WriteAsync("Hello from the /hello branch!");
});
});
app.MapGet("/", () => "This is the main branch.");
app.Run();
Here, a request to /hello
goes down a different path than a request to /
.
Quick Takeaway
Here’s a simple way to remember them:
Method | Purpose | Analogy | Calls next() ? |
---|---|---|---|
Use | Process and pass along the request. | A toll booth | Yes |
Run | Process and end the request. | A dead-end road | No |
Map | Branch the pipeline by path. | A fork in the road | N/A (creates a new pipeline) |
Understanding this flow control is key to building clean and efficient ASP.NET Core applications. Happy coding!
FAQ
What is the purpose of Use
in ASP.NET Core middleware?
Use
adds middleware to the pipeline that can process requests and optionally call the next middleware using next()
. It’s ideal for tasks like logging, authentication, or modifying requests and responses before passing them along.How does Run
differ from Use
in middleware?
Run
is a terminal middleware that ends the pipeline. Once a request hits a Run
delegate, no further middleware is executed. Use it for scenarios where you want to fully handle and terminate the request.What does Map
do in ASP.NET Core middleware?
Map
creates a branch in the middleware pipeline based on the request path. It allows you to define separate sub-pipelines for different URL segments, making it easy to organize logic for APIs, admin panels, or feature-specific routes.Can you use multiple Use
and Run
methods in the same pipeline?
Use
methods, but only one Run
should be used as it terminates the pipeline. Middleware after a Run
will never be executed.What happens if you forget to call next()
in a Use
middleware?
next()
, the pipeline stops at that middleware. This can be intentional for short-circuiting, but often it’s a source of bugs where downstream middleware doesn’t execute.When should you use Map
instead of conditional logic inside middleware?
Map
for cleanly separating logic by path, especially for large applications or APIs with distinct areas. It keeps your pipeline organized and avoids complex conditional statements inside middleware.How does middleware order affect request processing?
Is it possible to nest Map
branches?
Map
calls to create deeply branched pipelines for complex routing scenarios. Each branch can have its own middleware chain and terminal handlers.What are common mistakes with middleware registration?
Run
too early, forgetting to call next()
in Use
, or misplacing authentication and CORS middleware, leading to security or routing issues.How can you debug middleware pipeline issues?
See other aspnet-core posts
- How to Prevent Common Web Attacks in ASP.NET Core: Security Best Practices and Example
- Stop Repeating Yourself: Cleaner API Responses in ASP.NET Core
- Custom routing constraint in AspNet core
- Understanding dotnet dev-certs https: Local HTTPS for .NET Development
- ASP.NET Core HTTP Logging Middleware: 10 Practical Micro Tips
- Mastering Request and Response Body Logging in ASP.NET Core Middleware
- Recommended Middleware Order in ASP.NET Core for Secure, Fast, and Correct Pipelines
- Implementing Request Throttling Middleware in ASP.NET Core Using MemoryCache and Per-IP Limits