Ativação de middleware baseada em alocador no ASP.NET Core

IMiddlewareFactory/IMiddleware é um ponto de extensibilidade para a ativação de middleware que oferece os seguintes benefícios:

  • Ativação por solicitação de cliente (injeção de serviços com escopo)
  • Tipagem forte de middleware

Os métodos de extensão UseMiddleware verificam se o tipo registrado de um middleware implementa IMiddleware. Se isso acontecer, a instância IMiddlewareFactory registrada no contêiner será usada para resolver a implementação IMiddleware em vez de usar a lógica de ativação de middleware baseada em convenção. O middleware é registrado como um serviço com escopo ou transitório no contêiner de serviço do aplicativo.

IMiddleware é ativado por solicitação de cliente (conexão), de modo que os serviços com escopo possam ser injetados no construtor do middleware.

IMiddleware

IMiddleware define o middleware para o pipeline de solicitação do aplicativo. O método InvokeAsync(HttpContext, RequestDelegate) manipula as solicitações e retorna uma Task que representa a execução do middleware.

Middleware ativado por convenção:

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

As extensões são criadas para os middlewares:

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

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

Não é possível passar objetos para o middleware ativado por alocador com 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);
}

O middleware ativado por alocador é adicionado ao contêiner interno em Program.cs:

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddTransient<FactoryActivatedMiddleware>();

Ambos os middlewares estão registrados no pipeline de processamento de solicitação, também em Program.cs:

var app = builder.Build();

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

IMiddlewareFactory

IMiddlewareFactory fornece métodos para a criação do middleware. A implementação de alocador do middleware é registrada no contêiner como um serviço com escopo.

A implementação IMiddlewareFactory padrão, MiddlewareFactory, é encontrada no pacote Microsoft.AspNetCore.Http.

Recursos adicionais

IMiddlewareFactory/IMiddleware é um ponto de extensibilidade para a ativação de middleware.

Os métodos de extensão UseMiddleware verificam se o tipo registrado de um middleware implementa IMiddleware. Se isso acontecer, a instância IMiddlewareFactory registrada no contêiner será usada para resolver a implementação IMiddleware em vez de usar a lógica de ativação de middleware baseada em convenção. O middleware é registrado como um serviço com escopo ou transitório no contêiner de serviço do aplicativo.

Benefícios:

  • Ativação por solicitação de cliente (injeção de serviços com escopo)
  • Tipagem forte de middleware

IMiddleware é ativado por solicitação de cliente (conexão), de modo que os serviços com escopo possam ser injetados no construtor do middleware.

Exibir ou baixar código de exemplo (como baixar)

IMiddleware

IMiddleware define o middleware para o pipeline de solicitação do aplicativo. O método InvokeAsync(HttpContext, RequestDelegate) manipula as solicitações e retorna uma Task que representa a execução do middleware.

Middleware ativado por convenção:

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

As extensões são criadas para os 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>();
    }
}

Não é possível passar objetos para o middleware ativado por alocador com 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);
}

O middleware ativado por alocador é adicionado ao contêiner interno em Startup.ConfigureServices:

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

    services.AddTransient<FactoryActivatedMiddleware>();

    services.AddRazorPages();
}

Ambos os middlewares estão registrados no pipeline de processamento de solicitação em 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 fornece métodos para a criação do middleware. A implementação de alocador do middleware é registrada no contêiner como um serviço com escopo.

A implementação IMiddlewareFactory padrão, MiddlewareFactory, é encontrada no pacote Microsoft.AspNetCore.Http.

Recursos adicionais

IMiddlewareFactory/IMiddleware é um ponto de extensibilidade para a ativação de middleware.

Os métodos de extensão UseMiddleware verificam se o tipo registrado de um middleware implementa IMiddleware. Se isso acontecer, a instância IMiddlewareFactory registrada no contêiner será usada para resolver a implementação IMiddleware em vez de usar a lógica de ativação de middleware baseada em convenção. O middleware é registrado como um serviço com escopo ou transitório no contêiner de serviço do aplicativo.

Benefícios:

  • Ativação por solicitação de cliente (injeção de serviços com escopo)
  • Tipagem forte de middleware

IMiddleware é ativado por solicitação de cliente (conexão), de modo que os serviços com escopo possam ser injetados no construtor do middleware.

Exibir ou baixar código de exemplo (como baixar)

IMiddleware

IMiddleware define o middleware para o pipeline de solicitação do aplicativo. O método InvokeAsync(HttpContext, RequestDelegate) manipula as solicitações e retorna uma Task que representa a execução do middleware.

Middleware ativado por convenção:

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

As extensões são criadas para os 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>();
    }
}

Não é possível passar objetos para o middleware ativado por alocador com 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);
}

O middleware ativado por alocador é adicionado ao contêiner interno em 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 os middlewares estão registrados no pipeline de processamento de solicitação em 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 fornece métodos para a criação do middleware. A implementação de alocador do middleware é registrada no contêiner como um serviço com escopo.

A implementação IMiddlewareFactory padrão, MiddlewareFactory, é encontrada no pacote Microsoft.AspNetCore.Http.

Recursos adicionais