- Article
- 7 minutes to read
By Fiyaz Hasan, Rick Anderson, and Steve Smith
Middleware is software that's assembled into an app pipeline to handle requests and responses. ASP.NET Core provides a rich set of built-in middleware components, but in some scenarios you might want to write a custom middleware.
This topic describes how to write convention-based middleware. For an approach that uses strong typing and per-request activation, see Factory-based middleware activation in ASP.NET Core.
Middleware class
Middleware is generally encapsulated in a class and exposed with an extension method. Consider the following inline middleware, which sets the culture for the current request from a query string:
using System.Globalization;var builder = WebApplication.CreateBuilder(args);var app = builder.Build();app.UseHttpsRedirection();app.Use(async (context, next) =>{ var cultureQuery = context.Request.Query["culture"]; if (!string.IsNullOrWhiteSpace(cultureQuery)) { var culture = new CultureInfo(cultureQuery); CultureInfo.CurrentCulture = culture; CultureInfo.CurrentUICulture = culture; } // Call the next delegate/middleware in the pipeline. await next(context);});app.Run(async (context) =>{ await context.Response.WriteAsync( $"CurrentCulture.DisplayName: {CultureInfo.CurrentCulture.DisplayName}");});app.Run();
The preceding highlighted inline middleware is used to demonstrate creating a middleware component by calling Microsoft.AspNetCore.Builder.UseExtensions.Use. The preceding Use
extension method adds a middleware delegate defined in-line to the application's request pipeline.
There are two overloads available for the Use
extension:
- One takes a HttpContext and a
Func<Task>
. Invoke theFunc<Task>
without any parameters. - The other takes a
HttpContext
and a RequestDelegate. Invoke theRequestDelegate
by passing theHttpContext
.
Prefer using the later overload as it saves two internal per-request allocations that are required when using the other overload.
Test the middleware by passing in the culture. For example, request https://localhost:5001/?culture=es-es
.
For ASP.NET Core's built-in localization support, see Globalization and localization in ASP.NET Core.
The following code moves the middleware delegate to a class:
using System.Globalization;namespace Middleware.Example;public class RequestCultureMiddleware{ private readonly RequestDelegate _next; public RequestCultureMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { var cultureQuery = context.Request.Query["culture"]; if (!string.IsNullOrWhiteSpace(cultureQuery)) { var culture = new CultureInfo(cultureQuery); CultureInfo.CurrentCulture = culture; CultureInfo.CurrentUICulture = culture; } // Call the next delegate/middleware in the pipeline. await _next(context); }}
The middleware class must include:
- A public constructor with a parameter of type RequestDelegate.
- A public method named
Invoke
orInvokeAsync
. This method must:- Return a
Task
. - Accept a first parameter of type HttpContext.
- Return a
Additional parameters for the constructor and Invoke
/InvokeAsync
are populated by dependency injection (DI).
Typically, an extension method is created to expose the middleware through IApplicationBuilder:
using System.Globalization;namespace Middleware.Example;public class RequestCultureMiddleware{ private readonly RequestDelegate _next; public RequestCultureMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { var cultureQuery = context.Request.Query["culture"]; if (!string.IsNullOrWhiteSpace(cultureQuery)) { var culture = new CultureInfo(cultureQuery); CultureInfo.CurrentCulture = culture; CultureInfo.CurrentUICulture = culture; } // Call the next delegate/middleware in the pipeline. await _next(context); }}public static class RequestCultureMiddlewareExtensions{ public static IApplicationBuilder UseRequestCulture( this IApplicationBuilder builder) { return builder.UseMiddleware<RequestCultureMiddleware>(); }}
The following code calls the middleware from Program.cs
:
using Middleware.Example;using System.Globalization;var builder = WebApplication.CreateBuilder(args);var app = builder.Build();app.UseHttpsRedirection();app.UseRequestCulture();app.Run(async (context) =>{ await context.Response.WriteAsync( $"CurrentCulture.DisplayName: {CultureInfo.CurrentCulture.DisplayName}");});app.Run();
Middleware dependencies
Middleware should follow the Explicit Dependencies Principle by exposing its dependencies in its constructor. Middleware is constructed once per application lifetime.
Middleware components can resolve their dependencies from dependency injection (DI) through constructor parameters. UseMiddleware can also accept additional parameters directly.
Per-request middleware dependencies
Middleware is constructed at app startup and therefore has application lifetime. Scoped lifetime services used by middleware constructors aren't shared with other dependency-injected types during each request. To share a scoped service between middleware and other types, add these services to the InvokeAsync
method's signature. The InvokeAsync
method can accept additional parameters that are populated by DI:
namespace Middleware.Example;public class MyCustomMiddleware{ private readonly RequestDelegate _next; public MyCustomMiddleware(RequestDelegate next) { _next = next; } // IMessageWriter is injected into InvokeAsync public async Task InvokeAsync(HttpContext httpContext, IMessageWriter svc) { svc.Write(DateTime.Now.Ticks.ToString()); await _next(httpContext); }}public static class MyCustomMiddlewareExtensions{ public static IApplicationBuilder UseMyCustomMiddleware( this IApplicationBuilder builder) { return builder.UseMiddleware<MyCustomMiddleware>(); }}
Lifetime and registration options contains a complete sample of middleware with scoped lifetime services.
The following code is used to test the preceding middleware:
using Middleware.Example;var builder = WebApplication.CreateBuilder(args);builder.Services.AddScoped<IMessageWriter, LoggingMessageWriter>();var app = builder.Build();app.UseHttpsRedirection();app.UseMyCustomMiddleware();app.MapGet("/", () => "Hello World!");app.Run();
The IMessageWriter
interface and implementation:
namespace Middleware.Example;public interface IMessageWriter{ void Write(string message);}public class LoggingMessageWriter : IMessageWriter{ private readonly ILogger<LoggingMessageWriter> _logger; public LoggingMessageWriter(ILogger<LoggingMessageWriter> logger) => _logger = logger; public void Write(string message) => _logger.LogInformation(message);}
Additional resources
- Sample code used in this article
- UseExtensions source on GitHub
- Lifetime and registration options contains a complete sample of middleware with scoped, transient, and singleton lifetime services.
- DEEP DIVE: HOW IS THE ASP.NET CORE MIDDLEWARE PIPELINE BUILT
- ASP.NET Core Middleware
- Test ASP.NET Core middleware
- Migrate HTTP handlers and modules to ASP.NET Core middleware
- App startup in ASP.NET Core
- Request Features in ASP.NET Core
- Factory-based middleware activation in ASP.NET Core
- Middleware activation with a third-party container in ASP.NET Core
By Rick Anderson and Steve Smith
Middleware is software that's assembled into an app pipeline to handle requests and responses. ASP.NET Core provides a rich set of built-in middleware components, but in some scenarios you might want to write a custom middleware.
Note
This topic describes how to write convention-based middleware. For an approach that uses strong typing and per-request activation, see Factory-based middleware activation in ASP.NET Core.
Middleware class
Middleware is generally encapsulated in a class and exposed with an extension method. Consider the following middleware, which sets the culture for the current request from a query string:
public class Startup{ public void Configure(IApplicationBuilder app) { app.Use(async (context, next) => { var cultureQuery = context.Request.Query["culture"]; if (!string.IsNullOrWhiteSpace(cultureQuery)) { var culture = new CultureInfo(cultureQuery); CultureInfo.CurrentCulture = culture; CultureInfo.CurrentUICulture = culture; } // Call the next delegate/middleware in the pipeline await next(); }); app.Run(async (context) => { await context.Response.WriteAsync( $"Hello {CultureInfo.CurrentCulture.DisplayName}"); }); }}
The preceding sample code is used to demonstrate creating a middleware component. For ASP.NET Core's built-in localization support, see Globalization and localization in ASP.NET Core.
Test the middleware by passing in the culture. For example, request https://localhost:5001/?culture=no
.
The following code moves the middleware delegate to a class:
using Microsoft.AspNetCore.Http;using System.Globalization;using System.Threading.Tasks;namespace Culture{ public class RequestCultureMiddleware { private readonly RequestDelegate _next; public RequestCultureMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { var cultureQuery = context.Request.Query["culture"]; if (!string.IsNullOrWhiteSpace(cultureQuery)) { var culture = new CultureInfo(cultureQuery); CultureInfo.CurrentCulture = culture; CultureInfo.CurrentUICulture = culture; } // Call the next delegate/middleware in the pipeline await _next(context); } }}
The middleware class must include:
- A public constructor with a parameter of type RequestDelegate.
- A public method named
Invoke
orInvokeAsync
. This method must:- Return a
Task
. - Accept a first parameter of type HttpContext.
- Return a
Additional parameters for the constructor and Invoke
/InvokeAsync
are populated by dependency injection (DI).
Middleware dependencies
Middleware should follow the Explicit Dependencies Principle by exposing its dependencies in its constructor. Middleware is constructed once per application lifetime. See the Per-request middleware dependencies section if you need to share services with middleware within a request.
Middleware components can resolve their dependencies from dependency injection (DI) through constructor parameters. UseMiddleware can also accept additional parameters directly.
Per-request middleware dependencies
Because middleware is constructed at app startup, not per-request, scoped lifetime services used by middleware constructors aren't shared with other dependency-injected types during each request. If you must share a scoped service between your middleware and other types, add these services to the InvokeAsync
method's signature. The InvokeAsync
method can accept additional parameters that are populated by DI:
public class CustomMiddleware{ private readonly RequestDelegate _next; public CustomMiddleware(RequestDelegate next) { _next = next; } // IMyScopedService is injected into InvokeAsync public async Task InvokeAsync(HttpContext httpContext, IMyScopedService svc) { svc.MyProperty = 1000; await _next(httpContext); }}
Lifetime and registration options contains a complete sample of middleware with scoped lifetime services.
Middleware extension method
The following extension method exposes the middleware through IApplicationBuilder:
using Microsoft.AspNetCore.Builder;namespace Culture{ public static class RequestCultureMiddlewareExtensions { public static IApplicationBuilder UseRequestCulture( this IApplicationBuilder builder) { return builder.UseMiddleware<RequestCultureMiddleware>(); } }}
The following code calls the middleware from Startup.Configure
:
public class Startup{ public void Configure(IApplicationBuilder app) { app.UseRequestCulture(); app.Run(async (context) => { await context.Response.WriteAsync( $"Hello {CultureInfo.CurrentCulture.DisplayName}"); }); }}
Additional resources
- Lifetime and registration options contains a complete sample of middleware with scoped, transient, and singleton lifetime services.
- ASP.NET Core Middleware
- Test ASP.NET Core middleware
- Migrate HTTP handlers and modules to ASP.NET Core middleware
- App startup in ASP.NET Core
- Request Features in ASP.NET Core
- Factory-based middleware activation in ASP.NET Core
- Middleware activation with a third-party container in ASP.NET Core
FAQs
How to write custom ASP.NET Core middleware? ›
For this, right click on the project or folder where you want to create middleware class and select Add -> New Item. This will open Add New Item popup. Search for word "middleware" in the top right search box as shown below. Select Middleware Class item and give it a name and click on Add button.
Can we create custom middleware in .NET Core? ›To configure the custom Middleware we need to use the UseMiddleware Extension method as app. UseMiddleware<MyCustomMiddleware1>(); So, modify the Configure method of the Startup class as shown below. Now save the changes and run the application and you should get the following response in the browser as expected.
How do I create a custom middleware in .NET Core 6? ›- A public constructor with a parameter of type RequestDelegate.
- A public method named Invoke or InvokeAsync . ...
- The first parameter should be of type HttpContext.
- To expose the Middleware, an extension method is created through IApplicationBuilder.
Middleware is software that's assembled into an app pipeline to handle requests and responses. ASP.NET Core provides a rich set of built-in middleware components, but in some scenarios you might want to write a custom middleware. This topic describes how to write convention-based middleware.
How do I make custom middleware? ›- php artisan make:middleware CheckStatus. After successfully create middleware, go to app/http/kernel.php and register your custom middleware here : ...
- step 2: Implement Logic In Middleware: ...
- step 3:Add Route. ...
- Step 4: Add Method In Controller.
We set up the middleware in ASP.NET using the Configure method of our Startup class. Inside the Configure() method, we will invoke the extension methods on the IApplicationBuilder interface to add middleware.
How do I create a custom attribute in .NET Core? ›Declaring Custom Attributes
We can define an attribute by creating a class. This class should inherit from the Attribute class. Microsoft recommends appending the 'Attribute' suffix to the end of the class's name. After that, each property of our derived class will be a parameter of the desired data type.
Middleware | Description |
---|---|
HTTP Logging | Logs HTTP Requests and Responses. |
HTTP Method Override | Allows an incoming POST request to override the method. |
HTTPS Redirection | Redirect all HTTP requests to HTTPS. |
HTTP Strict Transport Security (HSTS) | Security enhancement middleware that adds a special response header. |
Typically, 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. We can set the order of middleware execution in the request pipeline.
What are the 6 types of middleware? ›- Message Oriented Middleware. ...
- Object Middleware. ...
- Remote Procedure Call (RPC) Middleware. ...
- Database Middleware. ...
- Transaction Middleware. ...
- Portals. ...
- Embedded Middleware. ...
- Content-Centric Middleware.
What are the three types of middleware? ›
Middleware functions can be divided into three main categories: application-specific, information-exchange and management and support middleware.
What are the 2 types of middleware and what are they used for? ›Here are some commonly used types of middleware: Messaging middleware facilitates communications between distributed applications and services. Object or ORB middleware enables software components or objects to communicate and interact with a program -- such as containers -- across distributed systems.
Can you build mobile apps with .NET Core? ›Using the . NET Core infrastructure and the provided runtimes, developers can, nowadays, develop applications for mobile platforms such as iOS, Android, and UWP, as well as micro runtimes such as Windows IoT Core, Raspbian, and Tizen.
What is the difference between app run and app use middleware in .NET Core? ›The difference is, middleware defined using app. Use may call next middleware component in the pipeline. On the other hand, middlware defined using app. Run will never call subsequent middleware.
Which command is used to create a new middleware? ›Creating a middleware
Type the command php artisan make:middleware 'name of the middleware'. In the above screen, we type the command "php artisan make:middleware CheckAge" where CheckAge is the name of the middleware.
Middleware is a thing of the past. It was an old-fashion system-specific software that allowed data to move from point A to point B for retailers back in the day.
Is middleware still used? ›Data management, application services, messaging, authentication, and application programming interface (API) management are all commonly handled by middleware. Today middleware is the technological foundation for modern cloud-native architectures.
What is a middleware give two examples? ›Common middleware examples include database middleware, application server middleware, message-oriented middleware, web middleware, and transaction-processing monitors.
What is middleware in ASP.NET Core example? ›Middleware is a piece of code in an application pipeline used to handle requests and responses. For example, we may have a middleware component to authenticate a user, another piece of middleware to handle errors, and another middleware to serve static files such as JavaScript files, CSS files, images, etc.
What is the difference between middleware and filter? ›A middleware can run for all requests while filters will only run for requests that reach the EndpointMiddleware and execute an action from an API Controller or a Razor Page. Filters have access to MVC components (eg: ModelState or IActionResults ).
How do I add a config file to a .NET Core console application? ›
In a . NET core console application Configuration can be added using the ConfigurationBuilder class. Additionally, support for configuring the application using a Json file, environmental variables, command line or using a custom configuration provider can also be added.
Can we make our own custom attributes? ›We can create any custom attribute, by adding, data-, followed by the attribute name. Let's say, for example, we want to have a custom author attribute, which represents the author of a paragraph. We can do this with the following code shown below. Within the full HTML element, this would look like the following.
How do I create a custom attribute in SFCC? ›- go to Administration > Site Development > System Object Types.
- Click on product on the list.
- Go to Attribute Definitions tab.
- Select New.
- Create the attribute with the desired id and names and Save it.
- Then go to the Attribute Grouping tab.
- Click edit on the storefrontAttributes.
Steps to create a custom attribute directive
Assign the attribute directive name to the selector metadata of @Directive decorator. Use ElementRef class to access DOM to change host element appearance and behavior. Use @Input() decorator to accept user input in our custom directive.
Middleware components are only constructed once during the application's lifetime, which means they are singletons within the application. Dependencies injected via the constructor are captured for the application's lifetime.
Which middleware is best? ›- Flow Middleware Platform. ...
- IBM WebSphere Application Server. ...
- JBoss EAP. ...
- Oracle Fusion Middleware. ...
- Microsoft BizTalk Server. ...
- Temenos Fabric. ...
- TIBCO Connected Intelligence. ...
- WSO2 Carbon.
Middleware can be used for the entire request pipeline but Filters is only used within the Routing Middleware where we have an MVC pipeline so Middleware operates at the level of ASP.NET Core but Filters executes only when requests come to the MVC pipeline. Let's understand the difference using the Code Example.
Can you apply two middleware single route? ›Middleware groups may be allocated to routes and controller activities with the same syntax as a single middleware. Middleware groups make it more helpful to allot numerous middleware to a route at once.
How many middleware you can use? ›We can use more than one middleware on an Express app instance, which means that we can use more than one middleware inside app. use() or app. METHOD() .
How many json files are in .NET Core? ›Different configuration json files in ASP.net Core There are mainly 6 configuration JSON files in ASP.net Core.
How do I write Microservices in .NET Core? ›
- Step 1: Create a microservice (. ...
- Step 2: Update Dockerfile and docker-compose. ...
- Note: You can run the application using both Visual Studio and the Docker command line.
- Step 3: Run the application using Visual Studio.
- Sign into your nuget.org account or create an account if you don't have one already.
- Select your user name at upper right, and then select API Keys.
- Select Create, and provide a name for your key.
- Under Select Scopes, select Push.
- Under Select Packages > Glob Pattern, enter *.
- Select Create.
NET Core and . NET Framework. ASP.NET Core is the best framework for building microservices applications because it offers incredible benefits including cloud-based configurations, rapid development, and cross-platform support.
Is ASP.NET Core good for microservices? ›ASP.NET comes with built-in support for developing and deploying your microservices using Docker containers. . NET includes APIs to easily consume microservices from any application you build, including mobile, desktop, games, web, and more.
Does .NET core use NuGet? ›For . NET (including . NET Core), the Microsoft-supported mechanism for sharing code is NuGet, which defines how packages for . NET are created, hosted, and consumed, and provides the tools for each of those roles.
What is NuGet package in asp net core? ›NuGet can be used to automatically add files and references to your Visual Studio projects. You can use the Syncfusion ASP.NET Core NuGet packages without installing the Essential Studio or ASP.NET Core platform installation to development with the Syncfusion ASP.NET Core controls. From v16. 2.0.
How do I add a custom NuGet package? ›Open Visual Studio, and then select Tools > Options. Select NuGet Package Manager, and then select Package Sources. Enter your feed's Name and the Source URL you copied in the previous step, and then select the green (+) sign to add a new package source.