ASP.NET Core Middleware Fundamentals

Understand the building blocks of request processing in ASP.NET Core.

What is Middleware?

In ASP.NET Core, middleware is software that's assembled into an application pipeline to handle requests and responses. Each piece of middleware has the ability to:

This pipeline model provides a flexible and extensible way to build web applications. You can think of it as a series of components that a request passes through on its way to the server and on its way back to the client.

Analogy: Imagine a factory assembly line. Each station (middleware) performs a specific task on the product (request) before passing it to the next station.

The Request Pipeline

The ASP.NET Core middleware pipeline is configured in the Startup.cs file (or Program.cs in .NET 6+) within the Configure method.

Configuring the Pipeline

The order in which middleware components are added to the pipeline is crucial, as it determines the order in which they are executed. The pipeline is executed in the order of registration for incoming requests, and in the reverse order for outgoing responses.

// Example in Startup.cs (older .NET Core versions)
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                else
                {
                    app.UseExceptionHandler("/Error");
                    app.UseHsts();
                }

                app.UseHttpsRedirection();
                app.UseStaticFiles();
                app.UseRouting();
                app.UseAuthorization();

                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapRazorPages();
                    endpoints.MapControllers();
                });
            }

            // Example in Program.cs (.NET 6+)
            var builder = WebApplication.CreateBuilder(args);

            // Add services to the container.
            builder.Services.AddRazorPages();

            var app = builder.Build();

            // Configure the HTTP request pipeline.
            if (!app.Environment.IsDevelopment())
            {
                app.UseExceptionHandler("/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseRouting();
            app.UseAuthorization();

            app.MapRazorPages();

            app.Run();
            

Common Middleware Components

Creating Custom Middleware

You can create your own custom middleware to add specific functionality to your request pipeline.

Option 1: Using a Class with an Invoke Method

This is the most common and recommended approach.

public class MyCustomMiddleware
            {
                private readonly RequestDelegate _next;

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

                public async Task InvokeAsync(HttpContext context)
                {
                    // Do something before the next middleware
                    Console.WriteLine("Request entering custom middleware...");

                    await _next(context); // Call the next middleware in the pipeline

                    // Do something after the next middleware has run (response processing)
                    Console.WriteLine("Request exiting custom middleware...");
                }
            }

            // In Startup.Configure or Program.cs
            app.UseMiddleware<MyCustomMiddleware>();
            

Option 2: Using an Extension Method

Extension methods make it easier to add custom middleware to the pipeline.

public static class MiddlewareExtensions
            {
                public static IApplicationBuilder UseMyCustomMiddleware(this IApplicationBuilder builder)
                {
                    return builder.UseMiddleware<MyCustomMiddleware>();
                }
            }

            // In Startup.Configure or Program.cs
            app.UseMyCustomMiddleware();
            

Middleware Order Matters

The sequence in which middleware is invoked is critical. For example, UseRouting must be called before UseAuthorization so that the authorization middleware knows which endpoint to authorize against.

Consider the following common ordering:

  1. Error handling middleware (e.g., UseDeveloperExceptionPage, UseExceptionHandler)
  2. HTTPS redirection (UseHttpsRedirection)
  3. Static file serving (UseStaticFiles)
  4. UseRouting
  5. Authentication (UseAuthentication)
  6. Authorization (UseAuthorization)
  7. Custom middleware
  8. Endpoint routing (UseEndpoints or MapRazorPages, MapControllers)

Advanced Concepts