Middleware is a core concept in ASP.NET Core that allows developers to handle HTTP requests and responses efficiently. While .NET Core provides many built-in middleware components, creating custom middleware helps tailor application behavior to specific requirements.
This post covers how to create custom middleware in both older and newer versions of .NET Core, providing step-by-step explanations with examples.
Middleware in .NET Core is a component that executes in the request-response pipeline. It can:
Middleware components are executed in the order they are registered in the application.
In older versions (ASP.NET Core 2.x and below), middleware was added inside the Startup.cs
file within the Configure method:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMiddleware<CustomMiddleware>();
app.UseMvc();
}
Middleware classes followed a specific structure, including an Invoke method.
Starting from .NET Core 3.1 and later (including .NET 6, .NET 7, and .NET 8), middleware is registered in Program.cs
using a more simplified approach:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseMiddleware<CustomMiddleware>();
app.Run();
The Startup.cs
file is no longer required in newer versions.
In older versions, middleware was implemented as a separate class with an Invoke method.
public class CustomMiddleware
{
private readonly RequestDelegate _next;
public CustomMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
Console.WriteLine("Middleware executed before request");
await _next(context);
Console.WriteLine("Middleware executed after request");
}
}
Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMiddleware<CustomMiddleware>();
app.UseMvc();
}
In newer .NET versions, middleware implementation is streamlined.
public class CustomMiddleware
{
private readonly RequestDelegate _next;
public CustomMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
Console.WriteLine("Middleware executed before request");
await _next(context);
Console.WriteLine("Middleware executed after request");
}
}
Program.cs
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseMiddleware<CustomMiddleware>();
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from .NET Core!");
});
app.Run();
This demonstrates how middleware is now registered directly in Program.cs
without Startup.cs
.
Log each incoming request and its response status.
public class LoggingMiddleware
{
private readonly RequestDelegate _next;
public LoggingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
Console.WriteLine($"Request Path: {context.Request.Path}");
await _next(context);
Console.WriteLine($"Response Status: {context.Response.StatusCode}");
}
}
Handle authentication logic before requests reach controllers.
public class AuthMiddleware
{
private readonly RequestDelegate _next;
public AuthMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
if (!context.Request.Headers.ContainsKey("Authorization"))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Unauthorized");
return;
}
await _next(context);
}
}
Handle global exceptions efficiently.
app.UseExceptionHandler(errorApp =>
{
errorApp.Run(async context =>
{
context.Response.StatusCode = 500;
await context.Response.WriteAsync("An error occurred!");
});
});
Startup.cs
.Program.cs
.Custom middleware is a powerful tool in .NET Core applications. Understanding how middleware works in both older and newer versions helps developers write efficient, modular, and reusable code. By implementing middleware for logging, authentication, and error handling, applications can be more robust and scalable.
Now that you've learned how to create custom middleware step by step, try implementing your own middleware in a .NET Core project!
Comments