Custom Middleware In .NET 6.0

In my previous article, I explained built-in middleware and how to implement in-line middleware. Please refer to the link below for the article.

Now we are going to write a custom middleware so that we can avoid in-line middleware in Program.cs file. Custom middleware will be written in a separate class. Please find the points that we need to keep in mind when writing custom middleware.

The middleware class must include the following:

  1. A public constructor with a parameter of type RequestDelegate.
  2. A public method named Invoke or InvokeAsync . This method should return Task.
  3. The first parameter should be of type HttpContext
  4. To expose the Middleware, an extension method is created through IApplicationBuilder.
  5. Additional parameters for constructor and Invok/InvokeAsync can be populated via Dependency Injection.

Let us quickly jump into the Visual Studio and create a middleware. I will be using the below Tools for this tutorial:

  1. Visual Studio Community Edition 2022 (64-bit) – Preview (Version 17.3.0 Preview 4.0)
  2. .NET 6.0
  3. Minimal Web API
  4. Swagger

There are three approaches to creating custom middleware.

Approach 1

  1. Right click on Project- > Add-> New Item
  2. Search for Middleware in the Pop-up window
  3. Select Middleware Class, providing a meaningful name and click on “Add”

A class will be created as below with the default implementation:

namespace MiddlewareTutorial {
    // You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
    public class LoggingMiddleware {
        private readonly RequestDelegate _next;
        public LoggingMiddleware(RequestDelegate next) {
            _next = next;
        }
        public Task Invoke(HttpContext httpContext) {
            return _next(httpContext);
        }
    }
    // Extension method used to add the middleware to the HTTP request pipeline.
    public static class LoggingMiddlewareExtensions {
        public static IApplicationBuilder UseLoggingMiddleware(this IApplicationBuilder builder) {
            return builder.UseMiddleware < LoggingMiddleware > ();
        }
    }
}

Approach 2

  1. Add a new class with a meaningful name.
  2. Add the public constructor with parameter of type RequestDelegate.
  3. Add a method named Invoke/InvokeAsync with HttpContext as the first parameter and Task as its return type.
  4. Add an extension method through IApplicationBuilder for exposing the middleware.

The final class will be looks like below:

namespace MiddlewareTutorial {
    public class ClassWithNoImplementationMiddleware {
        private readonly RequestDelegate _next;
        public ClassWithNoImplementationMiddleware(RequestDelegate next) {
            _next = next;
        }
        public async Task InvokeAsync(HttpContext httpContext) {
            await httpContext.Response.WriteAsync("Hello Readers!, this from Customer Middleware...");
        }
    }
    // Extension method used to add the middleware to the HTTP request pipeline.
    public static class ClassWithNoImplementationMiddlewareExtensions {
        public static IApplicationBuilder UseClassWithNoImplementationMiddleware(this IApplicationBuilder builder) {
            return builder.UseMiddleware < ClassWithNoImplementationMiddleware > ();
        }
    }
}

Approach 3

  1. Create a class with a meaningful name
  2. Implement the interface IMiddleware

The class will look like the below:

namespace MiddlewareTutorial {
    public class ClassWithIMiddlewareInterface: IMiddleware {
        public Task InvokeAsync(HttpContext context, RequestDelegate next) {
            throw new NotImplementedException();
        }
    }
}

Let us quickly check a simple custom middleware example and how it can be used in Program.cs. I will use the sample code seen in Approach 2.

public async Task InvokeAsync(HttpContext httpContext) {
    await httpContext.Response.WriteAsync("Hello Readers, this is from Custom Middleware...");
}

Now let us use this middleware into Program.cs class.

using MiddlewareTutorial;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) {
    app.UseClassWithNoImplementationMiddleware();
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.Run();

The output will look like the below:

Thank you for reading the article. I hope you have achieved an understanding of creating custom middleware. Please leave your feedback in the comments box below.

Next Recommended Reading UnitTest With AutoFixture In .NET 6.0