- Home
- .NET tutorials
- How to create and add custom middleware in ASP.NET Core
How to create and add custom middleware in ASP.NET Core
Published: Monday 4 March 2024
The great thing about ASP.NET Core is that it provides a number of built-in middleware components.
These include a rate-limiter where we can add a restriction on a number of HTTP requests that can be made based on certain parameters.
C# coding challenges
Another one is exception handling where the HTTP response can be written when a certain exception is thrown within the application.
However, there may be instances where a custom one needs to be added.
For example, there may be an instance where additional response headers need to be added to the HTTP request.
Creating a custom middleware
As part of the WebApplication
type used in Program.cs
, there is a Use
extension method. This extension method requires two parameters:
context
- An instance of theHttpContext
typenext
- Runs the next method in the middleware chain
As we have an instance of the HttpContext
, we are able to make changes to the response before it has started to be written.
In this example, we are adding a new HTTP response header stating that the X-Frame-Options
header should be set to SAMEORIGIN
.
// Program.cs
app.Use(async (context, next) =>
{
context.Response.Headers.Append("X-Frame-Options", "SAMEORIGIN");
await next();
});
This is a security feature that ensures that iframes can only be loaded in the same origin.
Cruicially, the next
parameter is invoked after it. What happens if we don't include that?
Short-circuiting
If we don't invoke the next
parameter, then none of the other middleware methods in the chain will be run.
// Program.cs
app.Use(async (HttpContext context, Func<Task> next) =>
{
context.Response.Headers.Append("X-Frame-Options", "SAMEORIGIN");
//await next();
});
This is known as short-circuiting, or terminal middleware. If we run a Web API request in this instance, the X-Frame-Options
header would get added to the HTTP response, but there is a good chance that the Web API response would not get returned.
Terminal middleware can also be used by calling app.Run
. This might be a good idea if we want to write our own holding page as it passes in the HttpContext type as the parameter.
// Program.cs
app.Run(async (context) =>
{
await context.Response.WriteAsync("<p>Holding page</p>");
});
Writing to the response after next has been called
If writing to the HTTP response, it's generally a good idea to write to it before calling the next()
method.
By doing it afterwards, there is a high chance that the HTTP response would have already started and therefore would throw unexpected behaviour and hidden exceptions.
// Program.cs
app.Use(async (HttpContext context, Func<Task> next) =>
{
await next();
context.Response.Headers.Append("X-Frame-Options", "SAMEORIGIN");
});
In this instance, if we executed an ASP.NET Core Web API endpoint, the X-Frame-Options
would not be added to the HTTP response headers as the HTTP response has already started.
Custom middleware in it's own class
As well as using app.Use
, custom middleware can be written to it's own class.
// HeaderMiddleware.cs
public class HeaderMiddleware
{
private readonly RequestDelegate _next;
public HeaderMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext)
{
httpContext.Response.Headers.Append("X-Frame-Options", "SAMEORIGIN");
await _next(httpContext);
}
}
A next
parameter is passed into the constructor which is stored as a private readonly field.
Then we add an Invoke
method, passing in an instance of HttpContext
. We add our X-Frame-Options
header to the HTTP response with a value of SAMEORIGIN
before invoking the next
method passing in the HttpContext
instance as a parameter.
The final thing we must do is register it to the WebApplication
instance in Program.cs
. We do that by calling the app.UseMiddleware
extension method:
// Program.cs
app.UseMiddleware<HeaderMiddleware>();
Watch our video
Watch our video where we show how to add custom middleware to an ASP.NET Core Web API and demonstrate what happens with short-circuiting and writing to the HTTP response after the next middleware in the chain has been invoked.