Activation d’un intergiciel (middleware) basé sur une fabrique dans ASP.NET CoreFactory-based middleware activation in ASP.NET Core

Par Luke LathamBy Luke Latham

IMiddlewareFactory/IMiddleware est un point d’extensibilité pour l’activation d’un middleware (intergiciel).IMiddlewareFactory/IMiddleware is an extensibility point for middleware activation.

Les méthodes d’extension de UseMiddleware vérifient si le type inscrit d’un middleware implémente IMiddleware.UseMiddleware extension methods check if a middleware's registered type implements IMiddleware. Si c’est le cas, l’instance de IMiddlewareFactory inscrite dans le conteneur est utilisée pour résoudre l’implémentation de IMiddleware, au lieu de la logique d’activation de middleware basée sur une convention.If it does, the IMiddlewareFactory instance registered in the container is used to resolve the IMiddleware implementation instead of using the convention-based middleware activation logic. Le middleware est inscrit comme service délimité ou temporaire dans le conteneur de service de l’application.The middleware is registered as a scoped or transient service in the app's service container.

Avantages :Benefits:

  • Activation par requête de client (injection de services délimités)Activation per client request (injection of scoped services)
  • Typage fort du middlewareStrong typing of middleware

IMiddleware est activé par requête de client (connexion) : des services délimités peuvent ainsi être injectés dans le constructeur du middleware.IMiddleware is activated per client request (connection), so scoped services can be injected into the middleware's constructor.

Affichez ou téléchargez l’exemple de code (procédure de téléchargement)View or download sample code (how to download)

IMiddlewareIMiddleware

IMiddleware définit le middleware pour le pipeline des requêtes de l’application.IMiddleware defines middleware for the app's request pipeline. La méthode InvokeAsync(HttpContext, RequestDelegate) gère les requêtes et retourne un élément Task qui représente l’exécution du middleware.The InvokeAsync(HttpContext, RequestDelegate) method handles requests and returns a Task that represents the execution of the middleware.

Middleware activé par convention :Middleware activated by convention:

public class ConventionalMiddleware
{
    private readonly RequestDelegate _next;

    public ConventionalMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context, AppDbContext db)
    {
        var keyValue = context.Request.Query["key"];

        if (!string.IsNullOrWhiteSpace(keyValue))
        {
            db.Add(new Request()
                {
                    DT = DateTime.UtcNow, 
                    MiddlewareActivation = "ConventionalMiddleware", 
                    Value = keyValue
                });

            await db.SaveChangesAsync();
        }

        await _next(context);
    }
}

Middleware activé par MiddlewareFactory :Middleware activated by MiddlewareFactory:

public class FactoryActivatedMiddleware : IMiddleware
{
    private readonly AppDbContext _db;

    public FactoryActivatedMiddleware(AppDbContext db)
    {
        _db = db;
    }

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        var keyValue = context.Request.Query["key"];

        if (!string.IsNullOrWhiteSpace(keyValue))
        {
            _db.Add(new Request()
                {
                    DT = DateTime.UtcNow, 
                    MiddlewareActivation = "FactoryActivatedMiddleware", 
                    Value = keyValue
                });

            await _db.SaveChangesAsync();
        }

        await next(context);
    }
}

Des extensions sont créées pour les middleware :Extensions are created for the middlewares:

public static class MiddlewareExtensions
{
    public static IApplicationBuilder UseConventionalMiddleware(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<ConventionalMiddleware>();
    }

    public static IApplicationBuilder UseFactoryActivatedMiddleware(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<FactoryActivatedMiddleware>();
    }
}

Il n’est pas possible de passer des objets au middleware activé par fabrique avec UseMiddleware :It isn't possible to pass objects to the factory-activated middleware with UseMiddleware:

public static IApplicationBuilder UseFactoryActivatedMiddleware(
    this IApplicationBuilder builder, bool option)
{
    // Passing 'option' as an argument throws a NotSupportedException at runtime.
    return builder.UseMiddleware<FactoryActivatedMiddleware>(option);
}

Le middleware activé par fabrique est ajouté au conteneur intégré dans Startup.ConfigureServices :The factory-activated middleware is added to the built-in container in Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<AppDbContext>(options =>
        options.UseInMemoryDatabase("InMemoryDb"));

    services.AddTransient<FactoryActivatedMiddleware>();

    services.AddRazorPages();
}

Les deux middlewares sont inscrits dans le pipeline de traitement des requêtes dans Startup.Configure :Both middlewares are registered in the request processing pipeline in Startup.Configure:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
    }

    app.UseConventionalMiddleware();
    app.UseFactoryActivatedMiddleware();

    app.UseStaticFiles();
    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

IMiddlewareFactoryIMiddlewareFactory

IMiddlewareFactory fournit des méthodes pour créer un middleware.IMiddlewareFactory provides methods to create middleware. L’implémentation de la fabrique de middlewares est inscrite dans le conteneur comme service délimité.The middleware factory implementation is registered in the container as a scoped service.

L’implémentation par défaut de IMiddlewareFactory, MiddlewareFactory, se trouve dans le package Microsoft.AspNetCore.Http.The default IMiddlewareFactory implementation, MiddlewareFactory, is found in the Microsoft.AspNetCore.Http package.

IMiddlewareFactory/IMiddleware est un point d’extensibilité pour l’activation d’un middleware (intergiciel).IMiddlewareFactory/IMiddleware is an extensibility point for middleware activation.

Les méthodes d’extension de UseMiddleware vérifient si le type inscrit d’un middleware implémente IMiddleware.UseMiddleware extension methods check if a middleware's registered type implements IMiddleware. Si c’est le cas, l’instance de IMiddlewareFactory inscrite dans le conteneur est utilisée pour résoudre l’implémentation de IMiddleware, au lieu de la logique d’activation de middleware basée sur une convention.If it does, the IMiddlewareFactory instance registered in the container is used to resolve the IMiddleware implementation instead of using the convention-based middleware activation logic. Le middleware est inscrit comme service délimité ou temporaire dans le conteneur de service de l’application.The middleware is registered as a scoped or transient service in the app's service container.

Avantages :Benefits:

  • Activation par requête de client (injection de services délimités)Activation per client request (injection of scoped services)
  • Typage fort du middlewareStrong typing of middleware

IMiddleware est activé par requête de client (connexion) : des services délimités peuvent ainsi être injectés dans le constructeur du middleware.IMiddleware is activated per client request (connection), so scoped services can be injected into the middleware's constructor.

Affichez ou téléchargez l’exemple de code (procédure de téléchargement)View or download sample code (how to download)

IMiddlewareIMiddleware

IMiddleware définit le middleware pour le pipeline des requêtes de l’application.IMiddleware defines middleware for the app's request pipeline. La méthode InvokeAsync(HttpContext, RequestDelegate) gère les requêtes et retourne un élément Task qui représente l’exécution du middleware.The InvokeAsync(HttpContext, RequestDelegate) method handles requests and returns a Task that represents the execution of the middleware.

Middleware activé par convention :Middleware activated by convention:

public class ConventionalMiddleware
{
    private readonly RequestDelegate _next;

    public ConventionalMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context, AppDbContext db)
    {
        var keyValue = context.Request.Query["key"];

        if (!string.IsNullOrWhiteSpace(keyValue))
        {
            db.Add(new Request()
                {
                    DT = DateTime.UtcNow, 
                    MiddlewareActivation = "ConventionalMiddleware", 
                    Value = keyValue
                });

            await db.SaveChangesAsync();
        }

        await _next(context);
    }
}

Middleware activé par MiddlewareFactory :Middleware activated by MiddlewareFactory:

public class FactoryActivatedMiddleware : IMiddleware
{
    private readonly AppDbContext _db;

    public FactoryActivatedMiddleware(AppDbContext db)
    {
        _db = db;
    }

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        var keyValue = context.Request.Query["key"];

        if (!string.IsNullOrWhiteSpace(keyValue))
        {
            _db.Add(new Request()
                {
                    DT = DateTime.UtcNow, 
                    MiddlewareActivation = "FactoryActivatedMiddleware", 
                    Value = keyValue
                });

            await _db.SaveChangesAsync();
        }

        await next(context);
    }
}

Des extensions sont créées pour les middleware :Extensions are created for the middlewares:

public static class MiddlewareExtensions
{
    public static IApplicationBuilder UseConventionalMiddleware(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<ConventionalMiddleware>();
    }

    public static IApplicationBuilder UseFactoryActivatedMiddleware(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<FactoryActivatedMiddleware>();
    }
}

Il n’est pas possible de passer des objets au middleware activé par fabrique avec UseMiddleware :It isn't possible to pass objects to the factory-activated middleware with UseMiddleware:

public static IApplicationBuilder UseFactoryActivatedMiddleware(
    this IApplicationBuilder builder, bool option)
{
    // Passing 'option' as an argument throws a NotSupportedException at runtime.
    return builder.UseMiddleware<FactoryActivatedMiddleware>(option);
}

Le middleware activé par fabrique est ajouté au conteneur intégré dans Startup.ConfigureServices :The factory-activated middleware is added to the built-in container in Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<AppDbContext>(options =>
        options.UseInMemoryDatabase("InMemoryDb"));

    services.AddTransient<FactoryActivatedMiddleware>();

    services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Les deux middlewares sont inscrits dans le pipeline de traitement des requêtes dans Startup.Configure :Both middlewares are registered in the request processing pipeline in Startup.Configure:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
    }

    app.UseConventionalMiddleware();
    app.UseFactoryActivatedMiddleware();

    app.UseStaticFiles();
    app.UseMvc();
}

IMiddlewareFactoryIMiddlewareFactory

IMiddlewareFactory fournit des méthodes pour créer un middleware.IMiddlewareFactory provides methods to create middleware. L’implémentation de la fabrique de middlewares est inscrite dans le conteneur comme service délimité.The middleware factory implementation is registered in the container as a scoped service.

L’implémentation par défaut de IMiddlewareFactory, MiddlewareFactory, se trouve dans le package Microsoft.AspNetCore.Http.The default IMiddlewareFactory implementation, MiddlewareFactory, is found in the Microsoft.AspNetCore.Http package.

Ressources supplémentairesAdditional resources