Activation d’un intergiciel (middleware) basé sur une fabrique dans ASP.NET Core

IMiddlewareFactory/IMiddleware est un point d’extensibilité pour l’activation d’intergiciel qui offre les avantages suivants :

  • Activation par requête de client (injection de services délimités)
  • Typage fort du middleware

Les méthodes d’extension de UseMiddleware vérifient si le type inscrit d’un middleware implémente 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. Le middleware est inscrit comme service délimité ou temporaire dans le conteneur de service de l’application.

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

IMiddleware définit le middleware pour le pipeline des requêtes de l’application. 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.

Middleware activé par convention :

public class ConventionalMiddleware
{
    private readonly RequestDelegate _next;

    public ConventionalMiddleware(RequestDelegate next)
        => _next = next;

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

        if (!string.IsNullOrWhiteSpace(keyValue))
        {
            dbContext.Requests.Add(new Request("Conventional", keyValue));

            await dbContext.SaveChangesAsync();
        }

        await _next(context);
    }
}

Middleware activé par MiddlewareFactory :

public class FactoryActivatedMiddleware : IMiddleware
{
    private readonly SampleDbContext _dbContext;

    public FactoryActivatedMiddleware(SampleDbContext dbContext)
        => _dbContext = dbContext;

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

        if (!string.IsNullOrWhiteSpace(keyValue))
        {
            _dbContext.Requests.Add(new Request("Factory", keyValue));

            await _dbContext.SaveChangesAsync();
        }

        await next(context);
    }
}

Des extensions sont créées pour les intergiciels :

public static class MiddlewareExtensions
{
    public static IApplicationBuilder UseConventionalMiddleware(
        this IApplicationBuilder app)
        => app.UseMiddleware<ConventionalMiddleware>();

    public static IApplicationBuilder UseFactoryActivatedMiddleware(
        this IApplicationBuilder app)
        => app.UseMiddleware<FactoryActivatedMiddleware>();
}

Il n’est pas possible de passer des objets au middleware activé par fabrique avec UseMiddleware :

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

Le middleware activé par fabrique est ajouté au conteneur intégré dans Program.cs :

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDbContext<SampleDbContext>
    (options => options.UseInMemoryDatabase("SampleDb"));

builder.Services.AddTransient<FactoryActivatedMiddleware>();

Les deux intergiciels sont inscrits dans le pipeline de traitement des requêtes, également dans Program.cs :

var app = builder.Build();

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

IMiddlewareFactory

IMiddlewareFactory fournit des méthodes pour créer un middleware. L’implémentation de la fabrique de middlewares est inscrite dans le conteneur comme service délimité.

L’implémentation par défaut de IMiddlewareFactory, MiddlewareFactory, se trouve dans le package Microsoft.AspNetCore.Http.

Ressources supplémentaires

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

Les méthodes d’extension de UseMiddleware vérifient si le type inscrit d’un middleware implémente 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. Le middleware est inscrit comme service délimité ou temporaire dans le conteneur de service de l’application.

Avantages :

  • Activation par requête de client (injection de services délimités)
  • Typage fort du 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.

Affichez ou téléchargez l’exemple de code (procédure de téléchargement)

IMiddleware

IMiddleware définit le middleware pour le pipeline des requêtes de l’application. 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.

Middleware activé par 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 :

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 intergiciels :

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 :

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 :

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

    services.AddTransient<FactoryActivatedMiddleware>();

    services.AddRazorPages();
}

Les deux intergiciels sont inscrits dans le pipeline de traitement des requêtes dans 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();
    });
}

IMiddlewareFactory

IMiddlewareFactory fournit des méthodes pour créer un middleware. L’implémentation de la fabrique de middlewares est inscrite dans le conteneur comme service délimité.

L’implémentation par défaut de IMiddlewareFactory, MiddlewareFactory, se trouve dans le package Microsoft.AspNetCore.Http.

Ressources supplémentaires

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

Les méthodes d’extension de UseMiddleware vérifient si le type inscrit d’un middleware implémente 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. Le middleware est inscrit comme service délimité ou temporaire dans le conteneur de service de l’application.

Avantages :

  • Activation par requête de client (injection de services délimités)
  • Typage fort du 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.

Affichez ou téléchargez l’exemple de code (procédure de téléchargement)

IMiddleware

IMiddleware définit le middleware pour le pipeline des requêtes de l’application. 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.

Middleware activé par 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 :

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 intergiciels :

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 :

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 :

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

    services.AddTransient<FactoryActivatedMiddleware>();

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

Les deux intergiciels sont inscrits dans le pipeline de traitement des requêtes dans 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();
}

IMiddlewareFactory

IMiddlewareFactory fournit des méthodes pour créer un middleware. L’implémentation de la fabrique de middlewares est inscrite dans le conteneur comme service délimité.

L’implémentation par défaut de IMiddlewareFactory, MiddlewareFactory, se trouve dans le package Microsoft.AspNetCore.Http.

Ressources supplémentaires