When building an ASP.NET Core application, you can draw on various middleware components to inspect, route, or modify the request and response messages that flow through the pipeline. You can also write your own custom middleware in ASP.NET Core.
Typically, in an ASP.NET Core application pipeline, you have a chain of middleware components. In this article, we’ll discuss the ASP.NET Core middleware and how we can work with convention-based and factory approaches.
To use the code examples in this article, you must have Visual Studio 2022 installed on your system. If you don’t have a copy yet, you can download Visual Studio 2022 here.
Create an ASP.NET Core 7 Web API project in Visual Studio 2022
First, let’s create an ASP.NET Core 7 project in Visual Studio 2022. Follow these steps:
- Launch the Visual Studio 2022 IDE.
- Click Create New Project.
- In the Create New Project window, select ASP.NET Core Web API from the list of templates displayed.
- Click next.
- In the Configure Your New Project window, specify a name and location for the new project.
- Optionally check the box “Install the solution and the project in the same directory” depending on your preferences.
- Click next.
- In the next displayed “More information” window, leave the “Use controllers (check to use minimal APIs)” box checked. In this project we will not be using minimal APIs. Leave “Authentication Type” as “None” (default).
- Make sure the “Enable Open API Support”, “Configure for HTTPS” and “Enable docker” boxes are unchecked as we won’t be using those features here.
- Click Create.
We will use this ASP.NET Core 7 Web API project to work with factory middleware activation in the sections below.
Understanding middleware in ASP.NET Core
Middleware is the software components that comprise ASP.NET Core’s request/response processing pipeline. Incoming requests flow through each middleware component in the pipeline, and each of these components can either process the request or forward it to the next component in the pipeline.
Middleware can do many things, including authentication, authorization, logging, exception handling, routing, caching, and response compression. You can modularize the functionality of your application into individual components and add, remove, or rearrange middleware to tailor the request and response processing pipeline to your application.
Traditionally, when using a newer version of ASP.NET Core, you had to configure your middleware components using the UseMiddleware extension method in the Startup class or in the Program.cs file. In contrast, factory-based middleware activation allows middleware components to be defined and configured using factories, which provide greater activation flexibility.
Note that if you don’t write your own custom middleware factory class, the default middleware factory will be used. In ASP.NET Core, you can activate your middleware in two different ways: convention-based middleware activation and factory-based middleware activation. Let us now examine both approaches.
A convention-based middleware in ASP.NET Core
In ASP.NET Core, convention-based middleware activation is a feature that allows you to automatically apply middleware to the request/response pipeline based on predefined conventions, rather than explicitly configuring each middleware component. The following code listing shows how you can create a convention-based middleware component.
public class ConventionalMiddleware { private readonly RequestDelegate _next; public ConventionalMiddleware(RequestDelegate next) => _next = next; public async Task InvokeAsync(HttpContext context) { Trace.WriteLine("Inside the Conventional Middleware."); await _next(context); } }
You can add this middleware to the request processing pipeline using the following code in the Program.cs file.
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.UseMiddleware<ConventionalMiddleware>(); app.Run();
Factory middleware in ASP.NET Core
In ASP.NET Core, factory-based middleware activation is a more flexible and dynamic way to configure and activate middleware components. With factory-based middleware activation, you can customize the middleware deployment process based on the needs of your application.
Factory middleware allows you to inject dependencies that have a self-contained lifetime using the constructor of your middleware class, a feature not supported by convention-based middleware. A framework service lifetime means that the service is created once per client request and removed at the end of the request.
Factory middleware has the following advantages over traditional style or convention-based middleware:
- While a convention-based middleware is created once when an ASP.NET Core application runs, a factory-based middleware is created with each request.
- Because factory-based middleware provides support for per-request activation, you can inject included services into the middleware constructor.
- Factory firmware supports strong middleware input.
To use factory-based firmware activation, you need to follow the four steps below.
- Create a class that represents your middleware component and implements the IMiddleware interface.
- Implement the InvokeAsync method in your middleware, which defines the middleware logic.
- Add the middleware to the DI container using the AddSingleton or AddScoped method.
- Configure the middleware pipeline by using the UseMiddleware extension method and specifying your middleware component type.
The following code listing shows how you can write a factory-based middleware component.
public class FactoryActivatedMiddleware : IMiddleware { public async Task InvokeAsync(HttpContext context, RequestDelegate next) { Trace.WriteLine("Inside the Factory Activated Middleware."); await next.Invoke(context); } }
You must register the middleware with the services container using the following code.
var builder = WebApplication.CreateBuilder(args); builder.Services.AddTransient<FactoryActivatedMiddleware>();
Now you can add this middleware just like we added the middleware in the convention-based middleware example.
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.UseMiddleware<FactoryActivatedMiddleware>(); app.Run();
Each call to the UseMiddleware extension method checks whether or not the middleware implementation in question conforms to the IMiddleware interface. If this condition is met, the IMiddlewareFactory instance registered in the service container is used to resolve the implementation of the IMiddleware interface instead of the convention-based middleware implementation. This middleware is registered as a transient or included service inside the services container.
The IMiddlewareFactory interface defines two methods: the Create(Type) and Release(IMiddleware) methods. While the Create(Type) method is used to create the middleware for each request, the Release(IMiddleware) method releases an IMiddleware instance at the end of the request. The default implementation of IMiddlewareFactory is available in the Microsoft.AspNetCore.Http.MiddlewareFactory class.
Copyright © 2023 IDG Communications, Inc.