Activación de middleware basada en Factory en ASP.NET Core

IMiddlewareFactory/IMiddleware es un punto de extensibilidad para la activación de middleware que ofrece las siguientes ventajas:

  • Activación por solicitud de cliente (inyección de servicios con ámbito)
  • Tipado fuerte de middleware

Los métodos de extensión UseMiddleware comprueban si un tipo registrado de middleware implementa IMiddleware. Si es así, la instancia IMiddlewareFactory registrada en el contenedor se usa para resolver la implementación IMiddleware en lugar de usar la lógica de activación de middleware basado en convenciones. El middleware se registra como un servicio con ámbito o transitorio en el contenedor de servicios de la aplicación.

IMiddleware se activa por solicitud de cliente (conexión), por lo que los servicios con ámbito se pueden insertar en el constructor del middleware.

IMiddleware

IMiddleware define el middleware para la canalización de solicitudes de la aplicación. El método InvokeAsync(HttpContext, RequestDelegate) controla las solicitudes y devuelve una Task que representa la ejecución del middleware.

Middleware activado por convención:

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 activado por 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);
    }
}

Las extensiones se crean para el middleware:

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

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

No se pueden pasar objetos al middleware activado por Factory con 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);
}

El middleware activado por Factory se agrega al contenedor integrado en Program.cs:

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddTransient<FactoryActivatedMiddleware>();

Ambos middlewares se registran en la canalización de procesamiento de solicitudes en Program.cs:

var app = builder.Build();

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

IMiddlewareFactory

IMiddlewareFactory proporciona métodos para crear middleware. La implementación de Middleware Factory se registra en el contenedor como un servicio con ámbito.

La implementación IMiddlewareFactory predeterminada, MiddlewareFactory, se encuentra en el paquete Microsoft.AspNetCore.Http.

Recursos adicionales

IMiddlewareFactory/IMiddleware es un punto de extensibilidad para la activación de middleware.

Los métodos de extensión UseMiddleware comprueban si un tipo registrado de middleware implementa IMiddleware. Si es así, la instancia IMiddlewareFactory registrada en el contenedor se usa para resolver la implementación IMiddleware en lugar de usar la lógica de activación de middleware basado en convenciones. El middleware se registra como un servicio con ámbito o transitorio en el contenedor de servicios de la aplicación.

Ventajas:

  • Activación por solicitud de cliente (inyección de servicios con ámbito)
  • Tipado fuerte de middleware

IMiddleware se activa por solicitud de cliente (conexión), por lo que los servicios con ámbito se pueden insertar en el constructor del middleware.

Vea o descargue el código de ejemplo (cómo descargarlo)

IMiddleware

IMiddleware define el middleware para la canalización de solicitudes de la aplicación. El método InvokeAsync(HttpContext, RequestDelegate) controla las solicitudes y devuelve una Task que representa la ejecución del middleware.

Middleware activado por convención:

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 activado por 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);
    }
}

Las extensiones se crean para el middleware:

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>();
    }
}

No se pueden pasar objetos al middleware activado por Factory con 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);
}

El middleware activado por Factory se agrega al contenedor integrado en Startup.ConfigureServices:

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

    services.AddTransient<FactoryActivatedMiddleware>();

    services.AddRazorPages();
}

Ambos middlewares se registran en la canalización de procesamiento de solicitudes en 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 proporciona métodos para crear middleware. La implementación de Middleware Factory se registra en el contenedor como un servicio con ámbito.

La implementación IMiddlewareFactory predeterminada, MiddlewareFactory, se encuentra en el paquete Microsoft.AspNetCore.Http.

Recursos adicionales

IMiddlewareFactory/IMiddleware es un punto de extensibilidad para la activación de middleware.

Los métodos de extensión UseMiddleware comprueban si un tipo registrado de middleware implementa IMiddleware. Si es así, la instancia IMiddlewareFactory registrada en el contenedor se usa para resolver la implementación IMiddleware en lugar de usar la lógica de activación de middleware basado en convenciones. El middleware se registra como un servicio con ámbito o transitorio en el contenedor de servicios de la aplicación.

Ventajas:

  • Activación por solicitud de cliente (inyección de servicios con ámbito)
  • Tipado fuerte de middleware

IMiddleware se activa por solicitud de cliente (conexión), por lo que los servicios con ámbito se pueden insertar en el constructor del middleware.

Vea o descargue el código de ejemplo (cómo descargarlo)

IMiddleware

IMiddleware define el middleware para la canalización de solicitudes de la aplicación. El método InvokeAsync(HttpContext, RequestDelegate) controla las solicitudes y devuelve una Task que representa la ejecución del middleware.

Middleware activado por convención:

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 activado por 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);
    }
}

Las extensiones se crean para el middleware:

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>();
    }
}

No se pueden pasar objetos al middleware activado por Factory con 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);
}

El middleware activado por Factory se agrega al contenedor integrado en Startup.ConfigureServices:

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

    services.AddTransient<FactoryActivatedMiddleware>();

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

Ambos middlewares se registran en la canalización de procesamiento de solicitudes en 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 proporciona métodos para crear middleware. La implementación de Middleware Factory se registra en el contenedor como un servicio con ámbito.

La implementación IMiddlewareFactory predeterminada, MiddlewareFactory, se encuentra en el paquete Microsoft.AspNetCore.Http.

Recursos adicionales