ASP.NET Core  

Middlewares in ASP.NET Core — The Ultimate Detailed Guide

ASP.NET Core introduces a revolutionary, high-performance, composable request-processing system known as the Middleware Pipeline. Middlewares form the foundation of how requests and responses flow through an ASP.NET Core application.

Whether you're building REST APIs, MVC applications, or microservices, understanding middleware is essential. They control:

  • Authentication

  • Routing

  • Error handling

  • Logging

  • Security

  • Performance

  • Request/response manipulation

This is not just a basic guide — this is a complete deep dive into how middlewares work internally, how to build them, how to optimize them, and how they fit into enterprise architectures.

What is Middleware in ASP.NET Core?

A middleware is a small, self-contained component that processes HTTP requests. Every incoming request and outgoing response passes through a sequence of middlewares — forming the request pipeline.

Definition

Middleware is a software component that is assembled into an application pipeline to handle requests and responses. Each middleware either processes the request or passes it to the next middleware.

The Middleware Pipeline — How It Really Works

Here is the conceptual flow of how an API request travels through middlewares:

              INCOMING REQUEST
                      ↓
        ┌───────────────────────────┐
        │  Middleware 1 (Logging)   │
        └───────────────────────────┘
                      ↓
        ┌───────────────────────────┐
        │  Middleware 2 (Auth)      │
        └───────────────────────────┘
                      ↓
        ┌───────────────────────────┐
        │  Middleware 3 (Routing)   │
        └───────────────────────────┘
                      ↓
              Endpoint (Controller)
                      ↓
        ┌───────────────────────────┐
        │  Middleware 3 (Routing)   │
        └───────────────────────────┘
                      ↑
        ┌───────────────────────────┐
        │  Middleware 2 (Auth)      │
        └───────────────────────────┘
                      ↑
        ┌───────────────────────────┐
        │  Middleware 1 (Logging)   │
        └───────────────────────────┘
                      ↑
                OUTGOING RESPONSE

This shows a bidirectional flow — most middlewares execute twice:

  • Once the request enters

  • Once, while the response leaves

Why Middlewares?

Before ASP.NET Core, developers relied on:

  • HTTP modules

  • HTTP handlers

  • Global.asax

  • Web.config pipeline

These were heavyweight, inflexible, difficult to customize, and not cross-platform.

Middlewares solve those issues:

  1. Extremely lightweight

  2. Easy to compose

  3. Modular

  4. Cross-platform

  5. Faster due to Kestrel

  6. Developer-friendly

  7. Fully configurable pipeline

Creating Middleware

A middleware must follow one rule:

It must accept a RequestDelegate and return a Task.

Full Custom Middleware Example

public class LoggingMiddleware
{
    private readonly RequestDelegate next;

    public LoggingMiddleware(RequestDelegate next)
    {
        next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        Console.WriteLine($"Incoming Request: {context.Request.Path}");
        await next(context);
        Console.WriteLine($"Outgoing Response: {context.Response.StatusCode}");
    }
}

Register This in the Program.cs

app.UseMiddleware<LoggingMiddleware>();

Use(), Run(), Map()

These three functions define the pipeline structure.

app.Use() — Middle layer (Can Continue Pipeline)

app.Use(async (context, next) =>
{
    Console.WriteLine("Before");
    await next.Invoke();
    Console.WriteLine("After");
});
  1. Before logic

  2. Calls next()

  3. After logic

Most middlewares use Use().

app.Run() — Terminal Middleware (Stops Pipeline)

app.Run(async context =>
{
    await context.Response.WriteAsync("End of Pipeline");
});
  1. Does not call next()

  2. Ends pipeline immediately

Often used for:

  • Custom 404 handler

  • Maintenance mode

app.Map() — Branching Middleware

app.Map("/admin", adminApp =>
{
    adminApp.Run(async context =>
    {
        await context.Response.WriteAsync("Admin Area");
    });
});
  1. Path-based branching

  2. Used for versioning, API partitioning

Order of Middlewares

Middleware order decides security, routing, and performance.

Correct order in real projects:

UseExceptionHandler
UseHttpsRedirection
UseStaticFiles
UseRouting
UseCors
UseAuthentication
UseAuthorization
UseSession
MapControllers

Wrong order example

UseAuthorization
UseAuthentication

This makes authorization run before authentication → user always appears unauthorized!

Built-in Middleware

ASP.NET Core includes many built-in middlewares:

1. Exception Handling Middleware

Handles global exceptions & logs errors.

app.UseExceptionHandler("/Home/Error");

Used for:

  • Production error handling

  • Removing sensitive data from responses

2. HTTPS Redirection Middleware

app.UseHttpsRedirection();

Automatically redirects all:

http:// → https://

3. Static Files Middleware

app.UseStaticFiles();

Serves files from:

wwwroot/css  
wwwroot/js  
wwwroot/images  

Important: Must be placed before routing.

4. CORS Middleware

app.UseCors("AllowOrigin");

Used in:

  • Angular + .NET

  • React + .NET

  • Mobile + .NET API

5. Authentication & Authorization

app.UseAuthentication();
app.UseAuthorization();

Authentication → Who are you? Authorization → What can you do?

6. Routing Middleware

app.UseRouting();

Maps routes to MVC or Minimal APIs.

Real-World Middleware Examples

These are crucial for interviews & enterprise apps.

Example 1: API Request Logging

public class RequestLoggingMiddleware
{
    private readonly RequestDelegate next;

    public RequestLoggingMiddleware(RequestDelegate next)
    {
        next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var requestTime = DateTime.Now;
        await next(context);
        var responseTime = DateTime.Now;
        Console.WriteLine($"Time Taken: {responseTime - requestTime}");
    }
}

Used in:

  • Audit logs

  • Performance diagnostics

Example 2: JWT Token Validation Middleware

Used in microservices.

if (!context.Request.Headers.ContainsKey("Authorization"))
{
    context.Response.StatusCode = 401;
    return;
}

Example 3: Global Response Wrapper

Many companies wrap JSON responses:

{
  "success": true,
  "data": {...},
  "message": "OK"
}

Middleware can standardize this format.

Middleware in Microservices Architecture

Middlewares become even more important in microservices, especially in:

  • API Gateway

  • Reverse Proxy

  • Authentication gateway

  • Rate limiting

  • Service routing

  • Load balancing decisions

Example: Using YARP (Yet Another Reverse Proxy) with custom routing middleware.

Middleware Performance Best Practices

  • Avoid heavy CPU operations

  • Use async – always

  • Cache results

  • Validate input early

  • Use distributed caching for high traffic

  • Apply logging carefully

Common Middleware Mistakes (Must Avoid)

  • Calling next() multiple times

  • Missing next() call → pipeline stops unexpectedly

  • Misplacing UseAuthentication

  • Doing DB operations inside middleware

  • Logging too much → performance drop

  • Writing blocking synchronous code

Middleware vs Filters vs Handlers

FeatureMiddlewareFiltersHandlers
ScopeEntire pipelineMVC/APIHTTP endpoint
PurposeLogging, routing, securityValidation, model bindingMinimal API endpoint
RunsBefore controllersInside controllersPer route

This article is written to help developers, learners, and professionals clearly understand Middlewares in ASP.NET Core with real-world explanations and practical examples. If you found this guide helpful, feel free to share it with others, bookmark it for future reference, or connect for more detailed .NET content, architecture insights, and interview preparation materials.