Introduction

Middleware components are one of the most important concepts in ASP.NET Core Web API development. They control how requests and responses flow through your application.

If you understand middleware properly, you can build powerful features like authentication, logging, exception handling, routing, and much more.

In this article, you will learn what middleware is, how it works internally, and how to create your own middleware step by step using simple language and real examples.

What is Middleware in ASP.NET Core?

Middleware is a piece of code that handles HTTP requests and responses.

It sits in the request pipeline and decides:

In simple words:

Middleware = Request + Processing + Response

Understanding the Request Pipeline

ASP.NET Core uses a pipeline where multiple middleware components are executed in sequence.

Flow:

Example flow:

Client → Middleware 1 → Middleware 2 → Middleware 3 → Controller → Response → Middleware 3 → Middleware 2 → Middleware 1 → Client

This is also called a "chain of responsibility" pattern.

How Middleware Works Internally

Each middleware has access to:

Basic structure:

public async Task InvokeAsync(HttpContext context)
{
    // Before next middleware

    await _next(context);

    // After next middleware
}

Key idea:

Built-in Middleware in ASP.NET Core

ASP.NET Core provides many built-in middleware components:

Example configuration:

app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.UseRouting();
app.MapControllers();

Order matters here. Changing order can break your application.

Why Middleware Order is Important

Middleware executes in the order it is added.

Example:

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

If reversed:

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

Authorization will fail because user is not authenticated yet.

So always maintain correct order.

Types of Middleware

There are three common ways to create middleware:

1. Inline Middleware

Defined directly in Program.cs

app.Use(async (context, next) =>
{
    Console.WriteLine("Request started");

    await next();

    Console.WriteLine("Response finished");
});

2. Convention-based Middleware

Custom class with Invoke or InvokeAsync method

public class LoggingMiddleware
{
    private readonly RequestDelegate _next;

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

    public async Task InvokeAsync(HttpContext context)
    {
        Console.WriteLine("Request incoming");

        await _next(context);

        Console.WriteLine("Response outgoing");
    }
}

Register it:

app.UseMiddleware<LoggingMiddleware>();

3. Factory-based Middleware

Uses IMiddleware interface (less common but useful with DI)

public class CustomMiddleware : IMiddleware
{
    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        await next(context);
    }
}

Register:

builder.Services.AddTransient<CustomMiddleware>();
app.UseMiddleware<CustomMiddleware>();

Creating Custom Middleware Step by Step

Let’s create a simple request logging middleware.

Step 1: Create Middleware Class

public class RequestLoggingMiddleware
{
    private readonly RequestDelegate _next;

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

    public async Task InvokeAsync(HttpContext context)
    {
        Console.WriteLine($"Request: {context.Request.Method} {context.Request.Path}");

        await _next(context);

        Console.WriteLine($"Response Status: {context.Response.StatusCode}");
    }
}

Step 2: Register Middleware

app.UseMiddleware<RequestLoggingMiddleware>();

Step 3: Test

Run API and hit any endpoint. You will see logs in console.

Short-Circuiting Middleware

Middleware can stop request pipeline.

Example:

app.Use(async (context, next) =>
{
    if (!context.Request.Headers.ContainsKey("Authorization"))
    {
        context.Response.StatusCode = 401;
        await context.Response.WriteAsync("Unauthorized");
        return;
    }

    await next();
});

Here request stops if header is missing.

Middleware vs Filters in ASP.NET Core

FeatureMiddlewareFilters
ScopeGlobalMVC only
ExecutionBefore MVCInside MVC
Use caseLogging, AuthAction-specific logic

Real-World Use Cases of Middleware

Middleware is used in:

Best Practices for Middleware

Common Mistakes to Avoid

Summary

Middleware in ASP.NET Core is a powerful concept that controls how HTTP requests and responses are handled. By understanding the request pipeline, middleware order, and how to build custom middleware, you can create scalable and maintainable web applications. Proper use of middleware improves performance, security, and overall application design.