Component |
Role |
Kestrel |
Handles HTTP connection |
Middleware pipeline |
Adds cross-cutting behavior (logging, auth, etc.) |
Routing |
Matches incoming request to endpoint |
Endpoint execution |
Runs controller, Razor page, or API logic |
Response middleware |
Can modify/log response before it leaves the server |
Kestrel sends response |
Final response goes back to the client |
app.Use
– Middleware with next delegate
Adds middleware to the pipeline that will run for every request.
It doesn’t end the request instead, it passes control to the next middleware using await next.Invoke().
// Use Middleware: This runs for all requests
app.Use(async (context, next) =>
{
// Do something before
await next.Invoke(); // Call the next middleware
// Do something after
});
app.Map – Branching middleware
Used to branch the pipeline based on request paths.
This middleware will only be executed if the request path matches the specified path.
app.Map("/about", appBuilder =>
{
appBuilder.Run(async context =>
{
await context.Response.WriteAsync("About Page");
});
});
app.Run – Terminal middleware
This middleware will always execute if no previous middleware short-circuits the pipeline and does not call any next middleware.
It is typically used at the end of the pipeline to generate a final response and stop further processing.
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from app.Run!");
});
Built-in middleware components in Asp.NET Core
Middleware components are pieces of code that are assembled into an application pipeline to handle requests and responses. ASP.NET Core provides several built-in middleware components to support common scenarios such as serving static files, handling authentication, routing requests, and more.
Middleware |
Description |
Static Files (UseStaticFiles ) |
Serves static files like HTML, CSS, JS, images, etc., from the wwwroot folder. |
Routing (UseRouting ) |
Matches the incoming HTTP requests to endpoints defined in the app. Required for endpoint routing. |
Endpoints (UseEndpoints ) |
Executes the matched endpoint (e.g., controller action, Razor Page, minimal API). |
Authentication (UseAuthentication ) |
Enables authentication logic (e.g., JWT, cookies, identity). Should be placed before authorization. |
Authorization (UseAuthorization ) |
Validates that the user is authorized to access certain resources. |
CORS (UseCors ) |
Enables Cross-Origin Resource Sharing (CORS) support to allow or restrict cross-origin requests. |
Exception Handling (UseExceptionHandler , UseDeveloperExceptionPage ) |
Handles exceptions globally and provides error responses. Dev page shows detailed errors. |
HTTPS Redirection (UseHttpsRedirection ) |
Redirects all HTTP requests to HTTPS. |
Session (UseSession ) |
Enables session state in web apps. Requires session services configuration. |
Cookie Policy (UseCookiePolicy ) |
Enables GDPR-compliant cookie handling, like consent checks. |
WebSockets (UseWebSockets ) |
Enables WebSocket support for real-time communication. |
Response Caching (UseResponseCaching ) |
Caches HTTP responses to improve performance. |
Middleware Pipeline in Program.cs
var builder = WebApplication.CreateBuilder(args);
// Add services
builder.Services.AddRouting();
builder.Services.AddAuthentication();
builder.Services.AddAuthorization();
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Middleware pipeline
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.Run();
Key Points
The order in which middleware components are added is critical. For example:
-
UseRouting()
→ before UseAuthorization()
-
UseAuthentication()
→ before UseAuthorization()
-
UseStaticFiles()
→ before routing so static content is served without hitting the MVC pipeline.
Custom Middleware
Creating custom middleware in ASP.NET Core allows you to insert your own logic into the HTTP request pipeline. This is useful for tasks like logging, custom authentication, modifying responses, or intercepting requests.
Step-by-step
-
Create the Middleware Class
-
Create an Extension Method
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
using System;
public class RequestLoggingMiddleware
{
private readonly RequestDelegate _next;
public RequestLoggingMiddleware(RequestDelegate next)
{
_next = next;
}
// Middleware logic
public async Task InvokeAsync(HttpContext context)
{
// Log the incoming request
Console.WriteLine($"[Request] {context.Request.Method} {context.Request.Path}");
await _next(context); // Call the next middleware
// Log the outgoing response
Console.WriteLine($"[Response] {context.Response.StatusCode}");
}
}
// Extension method for clean registration
public static class RequestLoggingMiddlewareExtensions
{
public static IApplicationBuilder UseRequestLogging(this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestLoggingMiddleware>();
}
}
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseHttpsRedirection();
// Register your custom middleware
app.UseMiddleware<RequestLoggingMiddleware>();
app.UseRouting();
app.UseAuthorization();
app.MapControllers();
app.Run();
Here are common interview questions and answers based on the topic “Mastering Middleware in ASP.NET Core: The Complete Guide to Request Pipeline”, suitable for .NET developer interviews:
🔹1. What is middleware in ASP.NET Core?
Answer
Middleware is software that's assembled into an application pipeline to handle requests and responses. Each component in the pipeline can either:
🔹 2. How is middleware registered in the request pipeline?
Answer
Middleware is registered in the Program.cs
or Startup.cs
using extension methods like app.Use
, app.Run
, and app.Map
.
Example
app.UseMiddleware<CustomMiddleware>();
🔹 3. What's the difference between app.Use
, app.Run
, and app.Map
?
Method |
Description |
Use |
Adds middleware that can call the next component. |
Run |
Terminates the pipeline; no further middleware is invoked. |
Map |
Branches the pipeline based on request path. |
Common interview questions and answers
1. What is middleware in ASP.NET Core?
Answer
Middleware is software that's assembled into an application pipeline to handle requests and responses. Each component in the pipeline can either:
2. How is middleware registered in the request pipeline?
Answer
Middleware is registered in the Program.cs
or Startup.cs
using extension methods like app.Use
, app.Run
, and app.Map
.
app.UseMiddleware<CustomMiddleware>();
3. What's the difference between app.Use
, app.Run
, and app.Map
?
Method |
Description |
Use |
Adds middleware that can call the next component. |
Run |
Terminates the pipeline, no further middleware is invoked. |
Map |
Branches the pipeline based on request path. |
4. Explain the order of middleware execution. Why is it important?
Middleware executes in the order it's registered. The order matters because:
-
Early middleware (like logging, exception handling) can wrap later middleware.
-
Authentication should be registered before authorization.
-
app.UseRouting()
should come before app.UseAuthorization()
.
5. How do you write a custom middleware in ASP.NET Core?
public class CustomMiddleware
{
private readonly RequestDelegate _next;
public CustomMiddleware(RequestDelegate next) => _next = next;
public async Task InvokeAsync(HttpContext context)
{
// Pre-processing logic
await _next(context); // Call next middleware
// Post-processing logic
}
}
Register it using
app.UseMiddleware<CustomMiddleware>();
6. What is the role of RequestDelegate
in middleware?
RequestDelegate
represents the next middleware in the pipeline. It is used to invoke the next component using:
await _next(context);
7. How do you implement global exception handling using middleware?
Create a middleware that wraps the pipeline in a try-catch block and returns a custom response on error.
Example
public class ExceptionMiddleware
{
private readonly RequestDelegate _next;
public ExceptionMiddleware(RequestDelegate next) => _next = next;
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
// Log and handle error
context.Response.StatusCode = 500;
await context.Response.WriteAsync("Internal Server Error");
}
}
}
8. What are terminal and non-terminal middleware?
-
Terminal Middleware: Ends the request pipeline (e.g., app.Run(...)
)
-
Non-terminal Middleware: Calls await next()
to pass control to the next middleware (e.g., app.Use(...)
)
9. How does middleware support dependency injection?
You can inject services into middleware through the constructor.
Example
public class LoggingMiddleware
{
private readonly ILogger<LoggingMiddleware> _logger;
public LoggingMiddleware(RequestDelegate next, ILogger<LoggingMiddleware> logger)
{
_logger = logger;
}
}
10. Can you explain a real-time scenario where middleware is useful?
- Authentication Middleware is used to validate tokens before requests reach controllers.
- Logging Middleware can log every incoming request and outgoing response for audit and debugging.
Middleware – Summary Notes
-
Definition: Middleware is a component in the HTTP request pipeline that can inspect, modify, or terminate HTTP requests and responses during processing.
-
Execution: Executes for every HTTP request, regardless of whether the target is MVC, Razor Pages, static files, or others.
-
Placement: Middleware is configured in Startup.cs
or Program.cs
using methods like:
-
app.Use(...)
– to call the next middleware in the pipeline
-
app.Run(...)
– to end the pipeline
-
app.Map(...)
– to branch the pipeline based on request path
-
Use Cases
-
Logging
-
Authentication & Authorization
-
CORS (Cross-Origin Resource Sharing)
-
Exception Handling
-
Response Compression
-
Localization
-
Request/Response Inspection
-
Request Redirection and Modification
-
Granularity: Middleware works at a global application level, affecting all incoming and outgoing requests.
Conclusion
Middleware plays a critical role in handling cross-cutting concerns across the application in a centralized and consistent way. It enables developers to build reusable, modular components that simplify request/response processing.
Mastering how and when to use middleware is essential for building robust, scalable, and maintainable ASP.NET Core applications. By strategically placing and organizing middleware, you can ensure better performance, cleaner code architecture, and improved application security.
Thank you for taking the time to read this post. I hope it has provided you with a clear understanding of middleware in ASP.NET Core and empowered you to apply it effectively in real-world applications.
Keep learning, keep experimenting, and keep building robust and scalable web solutions with confidence.