development

Creating Custom Middleware in ASP.NET Core – A Simple Step-by-Step Guide

If you’re diving into ASP.NET Core, you’ll hear the word middleware tossed around a lot. But don’t worry, it’s not as scary or complex as it sounds.

Middleware is essentially a piece of code that sits in the pipeline, processing incoming HTTP requests and outgoing responses. Think of it like a bouncer at a club, it checks who’s coming in, can change the rules, or even block entry based on certain conditions.

 What is Middleware in ASP.NET Core?

Middleware is software that handles requests and responses. In ASP.NET Core, each request to your web application passes through a pipeline composed of middleware components.

Each component:

  1. Receives the request
  2. Does something with it (like logging, authentication, etc.)
  3. Either passes it to the next middleware or short-circuits it and ends the pipeline

Here’s a simple view of how it flows:

scss

CopyEdit

Incoming Request → Middleware 1 → Middleware 2 → Middleware 3 → Endpoint (Controller)

                     ↑                      ↑

             (Do something)         (Maybe modify response)

 Built-In vs. Custom Middleware

ASP.NET Core has built-in middleware like:

  • UseRouting
  • UseAuthentication
  • UseAuthorization
  • UseEndpoints

But sometimes, you need your logic. Maybe you want to log requests in a specific format, check headers, or add a custom token validator. That’s where custom middleware comes in.

 How to Create Custom Middleware in ASP.NET Core

Alright, let’s roll up our sleeves and build a custom middleware from scratch.

Step 1: Create a New ASP.NET Core Project

If you haven’t already, fire up a new project:

bash

CopyEdit

dotnet new web -n CustomMiddlewareDemo

cd CustomMiddlewareDemo

Step 2: Create a Middleware Class

Let’s say we want to log the time taken for each request. Create a new class in your project called RequestTimingMiddleware.cs.

csharp

CopyEdit

public class RequestTimingMiddleware

{

    private readonly RequestDelegate _next;

    public RequestTimingMiddleware(RequestDelegate next)

    {

        _next = next;

    }

    public async Task InvokeAsync(HttpContext context)

    {

        var watch = Stopwatch.StartNew();

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

        watch.Stop();

        var timeTaken = watch.ElapsedMilliseconds;

        Console.WriteLine($”Request took {timeTaken} ms”);

    }

}

What’s happening here?

  • RequestDelegate _next is the next middleware in line.
  • InvokeAsync() is the method ASP.NET Core uses to execute your middleware.
  • We start a stopwatch before calling the next middleware, then log the time after it finishes.

Step 3: Create an Extension Method (Optional but Neat)

To make your middleware easy to add, create an extension method in a class called RequestTimingMiddlewareExtensions.cs:

csharp

CopyEdit

public static class RequestTimingMiddlewareExtensions

{

    public static IApplicationBuilder UseRequestTiming(this IApplicationBuilder builder)

    {

        return builder.UseMiddleware<RequestTimingMiddleware>();

    }

}

This lets us add the middleware in a clean, readable way in Startup.cs or Program.cs.

 Step 4: Register Your Middleware in the Pipeline

In .NET 6 or later, you’ll be using Program.cs. Add your middleware there:

csharp

CopyEdit

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.UseRequestTiming(); // Our custom middleware

app.MapGet(“/”, () => “Hello World!”);

app.Run();

Now, every time you hit the endpoint, you’ll see in the console how long the request took.

 Real-World Use Cases of Custom Middleware

Here are a few things you can use custom middleware for:

  • Logging request and response data
  • Checking API keys in headers
  • Redirecting based on custom logic
  • Handling exceptions in a centralised place
  • Injecting custom response headers

 Pro Tips

  • Always keep your middleware lightweight and fast.
  • Middleware is executed in the order you register it, so order matters!
  • Want to short-circuit the pipeline? Just don’t call _next(context).
  • Need services (like logging)? Inject them via the constructor using dependency injection.

 FAQs

Q1: Do I need to create a new class every time I want to make middleware?

Not necessarily. For simple logic, you can use inline middleware with app.Use().

Q2: Can middleware access route data or query strings?

Absolutely. Just use context.Request.Path, context.Request.Query, etc.

Q3: Can I use multiple custom middleware?

Yes, you can chain as many as needed. Just remember the order!

Q4: Is it possible to handle exceptions in middleware?

Yep! Writing a global error handler middleware is one of the most common use cases.

 Wrapping It All Up

Custom middleware in ASP.NET Core gives you full control over your application’s request and response process. It’s like inserting your logic right into the veins of your app. Whether it’s for logging, security, or custom headers, middleware is your go-to.

Leave a Reply

Your email address will not be published. Required fields are marked *