Slider

Difference Between Middleware and Filter in C#.

Learn when to use Middleware vs Filters in ASP.NET Core and how each fits into the request and MVC execution pipeline.
Middleware Vs Filter

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

Each middleware:
  1. Executes some logic before calling the next middleware
  2. Calls the next middleware using await _next(context)
  3. Executes logic after the next middleware completes (optional)
Example of Built-in Middleware:
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
Each of these is a middleware component registered in the pipeline.

Why do we need a Middleware?

Middleware helps to:
  • Handle requests globally.
  • Keep controllers clean.
  • Centralize logic like logging, security, and error handling.
  • Improve maintainability.

How To Create Custom Middleware?

There are multiple conditions where we need to create our own custom middleware to handle incoming requests and out going response. Let's learn how to create a custom middleware and register it in the existing pipeline.

Step 1: Create a Custom Middleware Class.

In this step, we create a middleware class that contains the actual logic to handle HTTP requests and responses.
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);
    }
}

Key Terms Explained
  • 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.

This step makes your middleware look and behave like a built-in middleware, allowing clean and readable registration in Program.cs.
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

Here, the middleware is added to the request pipeline, and its position determines when it runs.
var app = builder.Build();

app.UseRequestLogging(); // Custom middleware

app.MapControllers();

app.Run();

Now our custom Middleware is registered successfully and ready to execute for each http request and response.

What is the use of the Run, Use, and Map keywords in the Middleware pipeline?

In ASP.NET Core, Use, Run, and Map are used to configure the middleware pipeline. Each keyword has a specific purpose and behavior.

1. Use: Use is used to add middleware that can pass control to the next middleware.
app.Use(async (context, next) =>
{
    Console.WriteLine("Before next middleware");
    await next();
    Console.WriteLine("After next middleware");
});

2. Run: Run adds a terminal middleware that does not call the next middleware.
app.Run(async context =>
{
    await context.Response.WriteAsync("Request handled here");
});

3. Map: A map is used to branch the request pipeline based on URL path.
app.Map("/admin", adminApp =>
{
    adminApp.Run(async context =>
    {
        await context.Response.WriteAsync("Admin area");
    });
});
Only requests starting with /admin go through this branch.

Common Use Cases of Middleware
  • Global exception handling
  • Authentication & authorization
  • Logging and auditing
  • Request/response modification
  • CORS
  • Rate limiting

What is a Filter?

A Filter is a component in ASP.NET Core that allows you to run custom logic before or after a controller action executes.
Filters are part of the MVC/Web API pipeline, not the global middleware pipeline.

Filters are mainly used for action-level cross-cutting concerns, such as:
  • Authorization
  • Validation
  • Logging
  • Exception handling
  • Modifying responses

Types of Filters.

ASP.NET Core provides five types of filters, each executing at a specific stage of the MVC request pipeline. Filters help handle cross-cutting concerns such as authorization, validation, logging, caching, and exception handling.

1. Authorization Filters

Authorization filters run first in the filter pipeline. They determine whether a user is allowed to access a controller or action.

If authorization fails, the request is short-circuited, and the action never executes.

2. Resource Filters

Resource filters run before model binding and after action execution. They are useful for caching, short-circuiting, or resource initialization.

3. Action Filters (Most Common)

Action filters run before and after controller action methods. They are commonly used for logging, validation, and auditing.

4. Result Filters

Result filters run before and after the action result executes (like Ok(), View()). They are useful for modifying responses.

5. Exception Filters

Exception filters handle exceptions thrown by controller actions.

How do filters work?

In ASP.NET Core, filters execute around a controller action and allow you to run logic before and after specific stages of request processing. Unlike middleware, filters are MVC-specific and are tightly coupled with controllers and actions.

Let’s understand the execution flow step by step using a real example.

Filter Execution Flow:
When a request reaches an MVC controller, it passes through filters in the following order:
Request
Authorization Filter
Resource Filter
Action Filter (Before)
Controller Action
Action Filter (After)
Result Filter
Response
If an exception occurs, Exception Filters are invoked.

Example: Logging Action Filter.

Step 1: Create a Custom 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");
    }
}

Step 2: Apply Filter to Controller
[LogActionFilter]
public class ProductsController : Controller
{
    public IActionResult Get()
    {
        Console.WriteLine("Inside Controller Action");
        return Ok("Products");
    }
}

Step-by-Step Execution (What Happens Internally)

1. Request arrives at MVC: The request has already passed through middleware and is now handled by MVC.
2. Authorization Filters run: ASP.NET Core checks whether the request is authorized to access the action.
3. Resource Filters run: These execute before model binding and can short-circuit the request.
4. Action Filter – OnActionExecuting
Before Action Method
This runs just before the controller action executes.

5. Controller Action Executes
Inside Controller Action

6. Action Filter – OnActionExecuted
After Action Method
This runs immediately after the action method completes.

7. Result Filters execute: These run before and after the action result (e.g., Ok()).
8. Response is returned to the client.

Use Filters when:
  • 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)

Use Middleware when you need to handle cross-cutting concerns globally for every HTTP request, such as authentication, logging, CORS, or exception handling, and when the logic is not tied to MVC controllers. Use Filters when the logic is specific to MVC actions or controllers, requires access to action parameters, model state, or results, and should run before or after controller execution, such as validation, authorization at the action level, or action-specific logging.
0

No comments

Post a Comment

both, mystorymag

DON'T MISS

Tech News
© all rights reserved
made with by AlgoLesson
Table of Contents