Écrire un intergiciel (middleware) ASP.NET Core personnalisé
Remarque
Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 9 de cet article.
Avertissement
Cette version d’ASP.NET Core n’est plus prise en charge. Pour plus d’informations, consultez la Stratégie de prise en charge de .NET et .NET Core. Pour la version actuelle, consultez la version .NET 8 de cet article.
Important
Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.
Pour la version actuelle, consultez la version .NET 9 de cet article.
Par Fiyaz Hasan, Rick Anderson et Steve Smith
Un middleware est un logiciel qui est assemblé dans un pipeline d’application pour gérer les requêtes et les réponses. Même si ASP.NET Core propose une large palette de composants d’intergiciel (middleware) intégrés, dans certains scénarios, vous voudrez certainement écrire un intergiciel personnalisé.
Cette rubrique explique comment écrire un intergiciel basé sur une convention. Pour une approche qui utilise un typage fort et une activation par requête, consultez Activation d’intergiciels en usine dans ASP.NET Core.
Classe d’intergiciel (middleware)
Les intergiciels sont généralement encapsulés dans une classe et exposés avec une méthode d’extension. Prenez en compte l’intergiciel inclus suivant, qui définit la culture de la requête actuelle à partir d’une chaîne de requête :
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();
L’intergiciel inclus mis en évidence ci-dessus est utilisé pour illustrer la création d’un composant d’intergiciel en appelant Microsoft.AspNetCore.Builder.UseExtensions.Use. La méthode d’extension Use
précédente ajoute un délégué intergiciel défini comme inclus au pipeline de requête de l’application.
Deux surcharges sont disponibles pour l’extension Use
:
- La première exige un HttpContext et un
Func<Task>
. Appelez leFunc<Task>
sans aucun paramètre. - La seconde méthode exige un
HttpContext
et un RequestDelegate. Appelez leRequestDelegate
en passant leHttpContext
.
Préfère utiliser la seconde surcharge alors qu’il enregistre deux allocations internes par requête, qui sont nécessaires lors de l’utilisation de l’autre surcharge.
Testez l’intergiciel en transmettant la culture. Par exemple, demandez https://localhost:5001/?culture=es-es
.
Consultez Globalisation et localisation dans ASP.NET Core pour la prise en charge de la localisation intégrée d’ASP.NET Core.
Le code suivant déplace le délégué de l’intergiciel dans une classe :
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);
}
}
La classe d’intergiciel (middleware) doit inclure :
- Un constructeur public avec un paramètre de type RequestDelegate.
- Une méthode publique nommée
Invoke
ouInvokeAsync
. Cette méthode doit :- Retournez une
Task
. - Accepter un premier paramètre de type HttpContext.
- Retournez une
Les paramètres supplémentaires pour le constructeur et Invoke
/InvokeAsync
sont remplis par Injection de dépendance (DI).
En règle générale, une méthode d’extension est créée pour exposer l’intergiciel via 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>();
}
}
Le code suivant appelle l’intergiciel à partir de 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();
Dépendances de l’intergiciel (middleware)
L’intergiciel doit suivre le principe de dépendances explicites en exposant ses dépendances dans son constructeur. L’intergiciel est construit une fois par durée de vie d’application.
Les composants de middleware peuvent résoudre leurs dépendances à partir de l’injection de dépendances à l’aide des paramètres du constructeur. UseMiddleware peut également accepter des paramètres supplémentaires directement.
Dépendances de l’intergiciel (middleware) par requête
L’intergiciel est construit au démarrage de l’application et a donc une durée de vie d’application. Les services de durée de vie étendue utilisés par les constructeurs de l’intergiciel ne sont pas partagés avec d’autres types injectés par des dépendances lors de chaque requête. Si vous devez partager un service étendu entre votre intergiciel et d’autres types, ajoutez ces services à la signature de la méthode InvokeAsync
. La méthode InvokeAsync
peut accepter des paramètres supplémentaires qui sont renseignés par injection de dépendances :
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>();
}
}
Les options de durée de vie et d’inscription contiennent un exemple complet d’intergiciel avec des services de durée de vie étendue.
Le code suivant est utilisé pour tester l’intergiciel précédent :
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();
Interface IMessageWriter
et implémentation :
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);
}
Ressources supplémentaires
- Exemple de code utilisé dans cet article
- Source UseExtensions sur GitHub
- Les options de durée de vie et d’inscription contiennent un exemple complet de middleware avec des services de durée de vie délimitée, temporaire et singleton.
- PRÉSENTATION APPROFONDIE : COMMENT LE PIPELINE D’INTERGICIELS ASP.NET CORE EST-IL CRÉÉ ?
- Intergiciel (middleware) ASP.NET Core
- Tester les middlewares ASP.NET Core
- Migrer des gestionnaires et des modules HTTP vers des middlewares ASP.NET Core
- Démarrage d’une application dans ASP.NET Core
- Fonctionnalités de requête dans ASP.NET Core
- Activation d’un intergiciel (middleware) basé sur une fabrique dans ASP.NET Core
- Activation d’un intergiciel (middleware) avec un conteneur tiers dans ASP.NET Core
De Rick Anderson et Steve Smith
Un middleware est un logiciel qui est assemblé dans un pipeline d’application pour gérer les requêtes et les réponses. Même si ASP.NET Core propose une large palette de composants d’intergiciel (middleware) intégrés, dans certains scénarios, vous voudrez certainement écrire un intergiciel personnalisé.
Notes
Cette rubrique explique comment écrire un intergiciel basé sur une convention. Pour une approche qui utilise un typage fort et une activation par requête, consultez Activation d’intergiciels en usine dans ASP.NET Core.
Classe d’intergiciel (middleware)
Les intergiciels sont généralement encapsulés dans une classe et exposés avec une méthode d’extension. Prenez en compte le middleware suivant, qui définit la culture de la requête actuelle à partir d’une chaîne de requête :
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}");
});
}
}
L’exemple de code précédent est utilisé pour illustrer la création d’un composant de middleware. Consultez Globalisation et localisation dans ASP.NET Core pour la prise en charge de la localisation intégrée d’ASP.NET Core.
Testez l’intergiciel en transmettant la culture. Par exemple, demandez https://localhost:5001/?culture=no
.
Le code suivant déplace le délégué de l’intergiciel dans une classe :
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);
}
}
}
La classe d’intergiciel (middleware) doit inclure :
- Un constructeur public avec un paramètre de type RequestDelegate.
- Une méthode publique nommée
Invoke
ouInvokeAsync
. Cette méthode doit :- Retournez une
Task
. - Accepter un premier paramètre de type HttpContext.
- Retournez une
Les paramètres supplémentaires pour le constructeur et Invoke
/InvokeAsync
sont remplis par Injection de dépendance (DI).
Dépendances de l’intergiciel (middleware)
L’intergiciel doit suivre le principe de dépendances explicites en exposant ses dépendances dans son constructeur. L’intergiciel est construit une fois par durée de vie d’application. Consultez la section Dépendances des middlewares par requête si vous avez besoin de partager des services avec un middleware au sein d’une requête.
Les composants de middleware peuvent résoudre leurs dépendances à partir de l’injection de dépendances à l’aide des paramètres du constructeur. UseMiddleware peut également accepter des paramètres supplémentaires directement.
Dépendances de l’intergiciel (middleware) par requête
Étant donné que le middleware est construit au démarrage de l’application, et non par requête, les services de durée de vie délimités utilisés par les constructeurs du middleware ne sont pas partagés avec d’autres types injectés par des dépendances lors de chaque requête. Si vous devez partager un service délimité entre votre intergiciel et d’autres types, ajoutez-le à la signature de la méthode InvokeAsync
. La méthode InvokeAsync
peut accepter des paramètres supplémentaires qui sont renseignés par injection de dépendances :
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);
}
}
Les options de durée de vie et d’inscription contiennent un exemple complet d’intergiciel avec des services de durée de vie étendue.
Méthode d’extension d’intergiciel
La méthode d’extension suivante expose le middleware par le biais de IApplicationBuilder :
using Microsoft.AspNetCore.Builder;
namespace Culture
{
public static class RequestCultureMiddlewareExtensions
{
public static IApplicationBuilder UseRequestCulture(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestCultureMiddleware>();
}
}
}
Le code suivant appelle l’intergiciel à partir de Startup.Configure
:
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.UseRequestCulture();
app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"Hello {CultureInfo.CurrentCulture.DisplayName}");
});
}
}
Ressources supplémentaires
- Les options de durée de vie et d’inscription contiennent un exemple complet de middleware avec des services de durée de vie délimitée, temporaire et singleton.
- Intergiciel (middleware) ASP.NET Core
- Tester les middlewares ASP.NET Core
- Migrer des gestionnaires et des modules HTTP vers des middlewares ASP.NET Core
- Démarrage d’une application dans ASP.NET Core
- Fonctionnalités de requête dans ASP.NET Core
- Activation d’un intergiciel (middleware) basé sur une fabrique dans ASP.NET Core
- Activation d’un intergiciel (middleware) avec un conteneur tiers dans ASP.NET Core