What Is Middleware
Middleware is software executed as part of an application's request and response processing pipeline.
Middleware components are arranged in a pipeline and executed sequentially in the order they are registered. A middleware component can prevent further components in the pipeline from being called. Middleware allows developers to customise the behaviour of the request processing pipeline by adding or modifying components.
Middleware supported out of the box by Microsoft includes support for HSTS, HttpsRedirection, Static Files and more. Examples of ways to extend this include support for caching, logging, image processing, header injection and permissions policies.
The IMiddleware Interface
The interface IMiddleware allows developers to customise the middleware for the app's request pipeline. It handles requests and responses through the request pipeline. From Microsoft:
IMiddlewareFactory/IMiddleware is an extensibility point for Middleware activation that offers the following benefits:
- Activation per client request (injection of scoped services)
- Strong typing of middleware
An example is shown below:
public class MyMiddleware : IMiddleware
{
private readonly IMyService _myService;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
public MyMiddleware(IMyService myService, IUmbracoContextAccessor umbracoContextAccessor)
{
_myService = myService;
_umbracoContextAccessor = umbracoContextAccessor;
}
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
// Your custom middleware logic here using _myService
// ...
await next(context);
}
}
Middleware Component Execution Order
The middleware pipeline is configured in Program.cs.
Components are executed in the order they are added to the pipeline; Microsoft details the middleware order in full. The terminal middleware is Endpoint middleware; this is the last piece of middleware that will be executed before a response is sent to the client.
This means:
- Ordering of custom middleware must consider the pipeline and the pipeline components that come before and after it.
- Middleware must be add calls prior to
UseEndpoints()
method or, if developing with Umbraco, before.WithEndpoints()
method.
Umbraco
In Umbraco in Program.cs
the Middleware components can be registered before app.UseUmbraco()
as follows:
app.UseMiddleware<MyMiddleware>();
app.UseUmbraco()
.WithMiddleware(u =>
{
u.UseBackOffice();
u.UseWebsite();
})
.WithEndpoints(u =>
{
u.UseInstallerEndpoints();
u.UseBackOfficeEndpoints();
u.UseWebsiteEndpoints();
});
For any MiddleWare routine that relies on the UmbracoPipeline consider using the Middleware extension points that Umbraco provides.
Non-Umbraco Sites
For non-Umbraco Sites the middleware can be injected as follows into Program.cs
:
app.UseMiddleware<MyMiddleware>();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
....
});
Container Registration
Microsoft refers to the use of IMiddleware or IMiddlewareFactory as "factory-activated" middleware. For it to work correctly, it must be registered in the built-in container.
Umbraco
In Umbraco sites the IComposer pattern can be followed:
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.DependencyInjection;
public class MyMiddlewareComposer: IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.Services.AddTransient<MyMiddleware>();
}
}
Non-Umbraco Sites
Inject the middleware into the container, in Program.cs
as follows:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddTransient<FactoryActivatedMiddleware>();
Top Tips
- Too much middleware will slow the application down.
- Be mindful of execution order when adding middleware components.
Summary
The IMiddleware interface allows modification of incoming requests and outgoing responses. It creates an extension point for dependency injection/ inversion of control into Middleware. This enables the development of testable, robust applications.