.NET Core Middleware

Soulaiman Ghanem
Code Factory Berlin
4 min readMar 29, 2022
Background source: gas pipes — Free Stock Photo by 2happy on Stockvault.net

A middleware is nothing but a component (class) which is executed on every request in ASP.NET Core application. You can compare it to the HttpHandlers and HttpModules in the classic ASP.NET.

There will be multiple middleware in ASP.NET Core web application. It can be either framework provided middleware, added via NuGet or your own custom middleware.

The ASP.NET Core request pipeline consists of a sequence of request delegates, called one after the other. The following diagram demonstrates the concept. The thread of execution follows the black arrows.

Source: ASP.NET Core Middleware | Microsoft Docs

You can set the order of middleware execution in the request pipeline. Each middleware adds or modifies http request and optionally passes control to the next middleware component. The following figure illustrates the execution of middleware components. The following diagram shows the complete request processing pipeline for ASP.NET Core MVC and Razor Pages apps.

Source: ASP.NET Core Middleware | Microsoft Docs

Let’s briefly describe what these guys do:

  • When a request is received, generally first middleware configured is the Exception middleware. This is because it can handle any exception from any other parts of request processing. In development mode though, DeveloperExceptionPage middleware can be used instead of exception handler middleware.
  • Then HSTS middleware can be used to add the Strict-Transport-Security header.
  • The optional UseHttpsRedirection middleware might be used to redirect users to HTTPS endpoint.
  • Static Files middleware is to serve static files (js, CSS, images, etc) for a web app. It is a terminal middleware. So, any static files request would not go via subsequent middleware pipeline.
  • Routing middleware is to add the endpoint information to the request object. This information is later used by other middleware.
  • CORS middleware for applying CORS policies.
  • Authentication middleware to check if the user is authenticated
  • Authorization middleware to check if user is authorized to perform current operation.

There are other framework middleware like Session, localization, compression, caching and diagnostics…

Configure Middleware

Let’s install and use Diagnostics middleware. Diagnostics middleware is used for reporting and handling exceptions and errors in ASP.NET Core, and diagnosing Entity Framework Core migrations errors.

We should add Microsoft.AspNetCore.Diagnostics dependency (if it is not added) to the project.json file.

This package includes following middleware and extension methods for it. You check the whole namespaces here:

Microsoft.AspNetCore.Diagnostics Namespace | Microsoft Docs

We can call respective Use* extension methods to use the above middleware in the configure method of Startup class.

Let’s add welcomePage middleware which will display welcome page for the root path.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseWelcomePage();
//other code removed for clarity
}

The above example will display the following welcome page for each request.

Please note that you can configure middleware using 4 different extension methods:

  1. Use(): to chain a middleware in the pipeline.
  2. Run(): terminates chain. No other middleware method will run after this.
  3. MapWhen(): enables branching pipeline. Runs specified middleware if condition is met
  4. Map(): similar to MapWhen. Runs middleware if path requested by user equals path provided in parameter.

Add Custom Middleware

You can also create and add your own custom middleware into the request pipeline of ASP.NET Core application.

Take this middleware as an example:

stefanprodan/AspNetCoreRateLimit: ASP.NET Core rate limiting middleware (github.com)

The custom middleware component is like any other .NET class with Invoke() method. However, in order to execute next middleware in a sequence, it should have RequestDelegate type parameter in the constructor.

public class MyMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;

public MyMiddleware(RequestDelegate next, ILoggerFactory logFactory)
{
_next = next;

_logger = logFactory.CreateLogger("MyMiddleware");
}

public async Task Invoke(HttpContext httpContext)
{
_logger.LogInformation("MyMiddleware executing..");

await _next(httpContext); // calling next middleware

}
}

// Extension method used to add the middleware to the HTTP request pipeline.
public static class MyMiddlewareExtensions
{
public static IApplicationBuilder UseMyMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<MyMiddleware>();
}
}

Now, you need to add our custom middleware in the request pipeline by using Use extension method as shown below.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMyMiddleware();

app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}

You are all done!

Summary

When a request is received by .NET Core , it goes through a chain of middleware. Every middleware add some feature in the request pipeline on top of previous middleware. It can be either framework provided middleware, or custom middleware. The order of middleware is important and configuring it is done in the Startup class.

--

--