Écrire un intergiciel (middleware) ASP.NET Core personnaliséWrite custom ASP.NET Core middleware

Par Rick Anderson et Steve SmithBy Rick Anderson and 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.Middleware is software that's assembled into an app pipeline to handle requests and responses. 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é.ASP.NET Core provides a rich set of built-in middleware components, but in some scenarios you might want to write a custom middleware.

Classe d’intergiciel (middleware)Middleware class

Les intergiciels sont généralement encapsulés dans une classe et exposés avec une méthode d’extension.Middleware is generally encapsulated in a class and exposed with an extension method. Prenez en compte le middleware suivant, qui définit la culture de la requête actuelle à partir d’une chaîne de requête :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}");
        });

    }
}

L’exemple de code précédent est utilisé pour illustrer la création d’un composant de middleware.The preceding sample code is used to demonstrate creating a middleware component. Pour plus d’informations sur la prise en charge intégrée de la localisation par ASP.NET Core, consultez Globalisation et localisation dans ASP.NET Core.For ASP.NET Core's built-in localization support, see Globalisation et localisation dans ASP.NET Core.

Testez l’intergiciel en transmettant la culture.Test the middleware by passing in the culture. Par exemple, demandez https://localhost:5001/?culture=no.For example, request https://localhost:5001/?culture=no.

Le code suivant déplace le délégué de l’intergiciel dans une classe :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);
        }
    }
}

La classe d’intergiciel (middleware) doit inclure :The middleware class must include:

  • Un constructeur public avec un paramètre de type RequestDelegate.A public constructor with a parameter of type RequestDelegate.
  • Une méthode publique nommée Invoke ou InvokeAsync.A public method named Invoke or InvokeAsync. Cette méthode doit :This method must:
    • Retournez une Task.Return a Task.
    • Accepter un premier paramètre de type HttpContext.Accept a first parameter of type HttpContext.

Les paramètres supplémentaires pour le constructeur et Invoke/InvokeAsync sont remplis par Injection de dépendance (DI).Additional parameters for the constructor and Invoke/InvokeAsync are populated by dependency injection (DI).

Dépendances de l’intergiciel (middleware)Middleware dependencies

L’intergiciel doit suivre le principe de dépendances explicites en exposant ses dépendances dans son constructeur.Middleware should follow the Explicit Dependencies Principle by exposing its dependencies in its constructor. L’intergiciel est construit une fois par durée de vie d’application.Middleware is constructed once per application lifetime. 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.See the Per-request middleware dependencies section if you need to share services with middleware within a request.

Les composants de middleware peuvent résoudre leurs dépendances à partir de l’injection de dépendances à l’aide des paramètres du constructeur.Middleware components can resolve their dependencies from dependency injection (DI) through constructor parameters. UseMiddleware<T> peut également accepter des paramètres supplémentaires directement.UseMiddleware<T> can also accept additional parameters directly.

Dépendances de l’intergiciel (middleware) par requêtePer-request middleware dependencies

É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.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. Si vous devez partager un service délimité entre votre intergiciel et d’autres types, ajoutez-le à la signature de la méthode Invoke.If you must share a scoped service between your middleware and other types, add these services to the Invoke method's signature. La méthode Invoke peut accepter des paramètres supplémentaires qui sont renseignés par injection de dépendances :The Invoke 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 Invoke
    public async Task Invoke(HttpContext httpContext, IMyScopedService svc)
    {
        svc.MyProperty = 1000;
        await _next(httpContext);
    }
}

Méthode d’extension d’intergicielMiddleware extension method

La méthode d’extension suivante expose le middleware par le biais de IApplicationBuilder :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>();
        }
    }
}

Le code suivant appelle l’intergiciel à partir de Startup.Configure :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}");
        });
    }
}

Ressources supplémentairesAdditional resources