Previous Distributed Denial-of-Service (DDoS) HTTP Verbs in ASP.NET Core Next

Middleware in ASP.NET Core

Middleware in ASP.NET Core

Middleware in ASP.NET Core refers to software components that are assembled into an application pipeline to handle requests and responses. Each piece of middleware processes an HTTP request as it flows through the pipeline and can either process the request and optionally modify the HTTP response, or pass the request to the next piece of middleware in the pipeline. This allows for a modular and extensible way to handle various concerns like authentication, logging, error handling, and routing.

What Is Middleware?

Middleware is a delegate that processes requests and responses. Each middleware can:

  • Inspect or modify the incoming request.
  • Call the next middleware in the pipeline.
  • Inspect or modify the outgoing response.

Built-in Middleware in ASP.NET Core

In ASP.NET Core, built-in middleware refers to predefined components provided by the framework that participate in the HTTP request pipeline. These handle cross-cutting concerns like routing, authentication, static file serving, exception handling, and more.

Common Built-in Middleware Examples

Middleware Purpose
UseRouting() Matches incoming requests to route endpoints
UseAuthentication() Validates user credentials
UseAuthorization() Enforces access policies
UseStaticFiles() Serves static content like HTML, CSS, JS
UseExceptionHandler() Handles unhandled exceptions gracefully
UseCors() Enables Cross-Origin Resource Sharing

Example: Using UseStaticFiles() Middleware

This middleware serves static files from the wwwroot folder.

Setup in Program.cs:

var builder = WebApplication.CreateBuilder(args);

// Add services if needed
// builder.Services.Add...

var app = builder.Build();

// Enable serving static files from wwwroot
app.UseStaticFiles();

// Other middleware
app.UseRouting();
app.UseAuthorization();

app.MapControllers();

app.Run();

Folder Structure:

/wwwroot
   └── index.html

When a user navigates to http://localhost:5000/index.html, the UseStaticFiles() middleware intercepts the request and serves the file directly—no controller needed.

Custom Middleware in ASP.NET Core

To create custom middleware in ASP.NET Core, follow these steps:

Create a Middleware Class

Define a class that will act as your custom middleware. This class should have a constructor that accepts a RequestDelegate parameter, which represents the next middleware in the pipeline. It also needs an InvokeAsync method that takes an HttpContext parameter and performs the desired logic.

using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;

public class MyCustomMiddleware
{
    private readonly RequestDelegate _next;

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

    public async Task InvokeAsync(HttpContext context)
    {
        // Perform actions before the next middleware (e.g., logging, validation)
        Console.WriteLine($"Request received at: {DateTime.Now}");

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

        // Perform actions after the next middleware (e.g., modifying response)
        Console.WriteLine($"Response sent at: {DateTime.Now}");
    }
}

Create an Extension Method (Optional but Recommended)

To make adding your middleware to the pipeline more convenient and readable, create an extension method for IApplicationBuilder.

using Microsoft.AspNetCore.Builder;

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

Register and Use the Middleware

In your Program.cs file (or Startup.cs in older versions), register your middleware and add it to the request pipeline.

// In Program.cs
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// ...

var app = builder.Build();

// Configure the HTTP request pipeline.
// ...

app.UseMyCustomMiddleware(); // Use your custom middleware

// ... other middleware and routing

app.Run();

The order in which middleware components are added to the pipeline is crucial, as they are executed sequentially. Middleware placed earlier in the pipeline will execute before those placed later.

Built-in Middleware vs Custom Middleware in ASP.NET Core

Middleware components form the HTTP request/response pipeline in ASP.NET Core. They can be built-in or custom-developed to handle cross-cutting concerns such as logging, authentication, or error handling.

Aspect Built-in Middleware Custom Middleware
Definition Predefined components provided by ASP.NET Core framework. User-defined components implementing specific logic.
Examples UseRouting(), UseAuthentication(), UseAuthorization(), UseStaticFiles() Logging middleware, request timing, custom headers, IP filtering.
Implementation Configured via extension methods in Program.cs or Startup.cs. Created as a class with Invoke/InvokeAsync method or as an inline delegate.
Flexibility Limited to provided functionality (can be configured but not rewritten). Fully customizable to meet unique application needs.
Maintenance Maintained by Microsoft; updated with framework releases. Maintained by the development team; must be tested and updated manually.
Use Case Common, reusable concerns across many apps. Application-specific requirements not covered by built-in components.

Precautions When Using Middleware

  • Order Matters: Middleware is executed in the order it’s added. Misordering can break routing, authentication, or error handling.
  • Avoid Blocking Calls: Use async/await properly. Blocking calls (e.g., .Result, .Wait()) can cause deadlocks.
  • Don’t Swallow Exceptions: Always rethrow or handle exceptions properly to avoid silent failures.
  • Minimal Logic: Middleware should be lean. Heavy logic belongs in services or controllers.
  • Thread Safety: Avoid shared mutable state unless properly synchronized.
  • Respect Short-Circuiting: If you don’t call await _next(context), downstream middleware won’t execute.

Best Practices for Middleware Design

  • Use Extension Methods: Wrap middleware registration in clean extension methods for readability and reuse.
  • Inject Dependencies via DI: Avoid service locator patterns. Use constructor injection for services.
  • Log Strategically: Use structured logging (e.g., Serilog, ILogger) for traceability without clutter.
  • Isolate Concerns: Each middleware should handle one responsibility (e.g., logging, auth, timing).
  • Test in Isolation: Unit test middleware using TestServer or WebApplicationFactory.
  • Use Built-in Middleware When Possible: Avoid reinventing the wheel—leverage framework-provided components.

Middleware Production Checklist

  • ✅ Registered in correct order (UseRouting before UseEndpoints, etc.)
  • ✅ Handles exceptions gracefully
  • ✅ Uses async/await correctly
  • ✅ Logs key request/response data
  • ✅ Avoids unnecessary performance overhead
  • ✅ Unit tested with mock HttpContext

Middleware Quiz

  1. Which middleware must be placed before UseEndpoints()?
    • A. UseAuthorization
    • B. UseRouting ✅
    • C. UseStaticFiles
    • D. UseCors
  2. What happens if await _next(context) is not called in custom middleware?
    • A. The response is cached
    • B. Downstream middleware is skipped ✅
    • C. An exception is thrown
    • D. The request is redirected
  3. Which of the following is a built-in middleware?
    • A. RequestTimingMiddleware
    • B. UseStaticFiles ✅
    • C. IPFilterMiddleware
    • D. HeaderInjectorMiddleware

Middleware vs Filters vs IActionResult

Component Scope Execution Timing Use Case
Middleware Global (entire pipeline) Before routing and after response Logging, auth, error handling
Filters Per-controller or per-action Before/after action execution Validation, caching, authorization
IActionResult Action-level After controller logic Formatting response (JSON, View, etc.)

Related Topics

Back to Index
Previous Distributed Denial-of-Service (DDoS) HTTP Verbs in ASP.NET Core Next
*