In ASP.NET Core, both Middleware and Filters are used to handle cross-cutting concerns such as logging, authentication, authorization, and exception handling. Although they may appear similar, they operate at different levels of the request pipeline and serve different purposes.
Understanding this difference is very important for real-world projects and is a frequently asked interview topic.
What is Middleware?
Middleware is a component that sits in the ASP.NET Core request processing pipeline and handles HTTP requests and responses.
Every incoming request passes through a series of middleware components, and each middleware can:
- Inspect the request
- Modify the request or response
- Decide whether to pass control to the next middleware
Middleware is mainly used for cross-cutting concerns that apply to many or all requests.
When a request comes to an ASP.NET Core application, it flows through the middleware pipeline in the order in which they are registered.
Request Flow:
Request
→ Middleware 1
→ Middleware 2
→ Controller / Endpoint
← Middleware 2
← Middleware 1
Response
- Executes some logic before calling the next middleware
- Calls the next middleware using await _next(context)
- Executes logic after the next middleware completes (optional)
app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers();
Why do we need a Middleware?
- Handle requests globally.
- Keep controllers clean.
- Centralize logic like logging, security, and error handling.
- Improve maintainability.
How To Create Custom Middleware?
Step 1: Create a Custom Middleware Class.
public class RequestLoggingMiddleware { private readonly RequestDelegate _next; private readonly ILogger<RequestLoggingMiddleware> _logger; public RequestLoggingMiddleware( RequestDelegate next, ILogger<RequestLoggingMiddleware> logger) { _next = next; _logger = logger; } public async Task InvokeAsync(HttpContext context) { _logger.LogInformation( "Request Started: {Method} {Path}", context.Request.Method, context.Request.Path); await _next(context); _logger.LogInformation( "Response Finished: {StatusCode}", context.Response.StatusCode); } }
- RequestDelegate: A delegate representing the next middleware in the pipeline. It is calling _next(context) passes control forward.
- HttpContext: Represents the current HTTP request and response. It contains headers, body, method, status code, user info, etc.
- InvokeAsync Method: The method ASP.NET Core automatically calls for each request. This is where middleware logic lives.
- ILogger: Built-in logging abstraction used instead of Console.WriteLine. Supports logging levels and providers.
Step 2: Creating an Extension Method to Register Middleware.
public static class RequestLoggingMiddlewareExtensions { public static IApplicationBuilder UseRequestLogging( this IApplicationBuilder app) { return app.UseMiddleware<RequestLoggingMiddleware>(); } }
- Extension Method: A static method that adds new functionality to an existing type without modifying it.
- IApplicationBuilder: Used to build the HTTP request pipeline. It provides methods like Use, Run, and Map.
- UseMiddleware<T>(): Registers a middleware type into the pipeline and lets the framework manage its lifetime and dependencies.
- Fluent API: Returning app allows chaining multiple middleware registrations.
Step 3: Register the Middleware in the Program.cs
var app = builder.Build(); app.UseRequestLogging(); // Custom middleware app.MapControllers(); app.Run();
What is the use of the Run, Use, and Map keywords in the Middleware pipeline?
app.Use(async (context, next) => { Console.WriteLine("Before next middleware"); await next(); Console.WriteLine("After next middleware"); });
app.Run(async context => { await context.Response.WriteAsync("Request handled here"); });
app.Map("/admin", adminApp => { adminApp.Run(async context => { await context.Response.WriteAsync("Admin area"); }); });
- Global exception handling
- Authentication & authorization
- Logging and auditing
- Request/response modification
- CORS
- Rate limiting
What is a Filter?
- Authorization
- Validation
- Logging
- Exception handling
- Modifying responses
Types of Filters.
1. Authorization Filters
2. Resource Filters
3. Action Filters (Most Common)
4. Result Filters
5. Exception Filters
How do filters work?
Request
→ Authorization Filter
→ Resource Filter
→ Action Filter (Before)
→ Controller Action
→ Action Filter (After)
→ Result Filter
→ Response
Example: Logging Action Filter.
using Microsoft.AspNetCore.Mvc.Filters; public class LogActionFilter : IActionFilter { public void OnActionExecuting(ActionExecutingContext context) { Console.WriteLine("Before Action Method"); } public void OnActionExecuted(ActionExecutedContext context) { Console.WriteLine("After Action Method"); } }
[LogActionFilter] public class ProductsController : Controller { public IActionResult Get() { Console.WriteLine("Inside Controller Action"); return Ok("Products"); } }
Step-by-Step Execution (What Happens Internally)
Before Action Method
Inside Controller Action
After Action Method
- Logic is tied to MVC actions
- You need access to model/action parameters
- Behavior is controller/action specific
Middleware Vs Filter.
| Feature | Middleware | Filter |
|---|---|---|
| Scope | Global (entire application) | MVC / Controller / Action |
| Execution Level | Request pipeline (before MVC) | Inside the MVC pipeline |
| Access to Action Context | No | Yes |
| Order Control | Registration order in the Program.cs | Filter type and order attribute |
| Can Short-Circuit Request | Yes | Yes |
| Dependency on MVC | No | Yes |
| Runs for Static Files | Yes | No |
| Common Use Cases | Logging, Auth, Exception handling | Validation, Authorization, Action logging |
| Performance | Faster (framework-level) | Slightly slower (MVC-specific) |

No comments
Post a Comment