Factorybezogene Middlewareaktivierung in ASP.NET Core

IMiddlewareFactory/IMiddleware ist ein Erweiterbarkeitspunkt für die Middlewareaktivierung, die folgende Vorteile bietet:

  • Aktivierung pro Clientanforderung (Injektion von bereichsbezogenen Diensten)
  • Starke Typisierung der Middleware

Die Erweiterungsmethode UseMiddleware überprüft, ob der registrierte Typ einer Middleware IMiddleware implementiert. Falls dies der Fall ist, wird die im Container registrierte IMiddlewareFactory-Instanz im Container verwendet, um die IMiddleware-Implementierung aufzulösen, anstatt die konventionsbasierte Middlewareaktivierungslogik zu verwenden. Die Middleware wird als bereichsbezogener oder vorübergehender Dienst im Dienstcontainer der App registriert.

IMiddleware wird pro Clientanforderung (-verbindung) aktiviert, sodass bereichsbezogene Dienste in den Konstruktor der Middleware eingefügt werden können.

IMiddleware

IMiddleware definiert Middleware für die Anforderungspipeline der App. Die InvokeAsync(HttpContext, RequestDelegate)-Methode verarbeitet Anforderungen und gibt einen Task zurück, der für die Ausführung der Middleware steht.

Über Konventionen aktivierte Middleware:

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

Über MiddlewareFactory aktivierte Middleware:

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

Für die Middleware werden Erweiterungen erstellt:

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

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

Es ist nicht möglich, Objekte mit UseMiddleware an eine Middleware zu übergeben, die über eine Factory aktiviert wurde:

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

Die Middleware, die über eine Factory aktiviert wurde, wird dem integrierten Container in Program.cs hinzugefügt:

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddTransient<FactoryActivatedMiddleware>();

Beide Middlewares werden in der Anforderungsverarbeitungspipeline beispielsweise in Program.cs registriert:

var app = builder.Build();

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

IMiddlewareFactory

IMiddlewareFactory stellt Methoden zur Verfügung, um die Middleware zu erstellen. Die Implementierung der Middlewarefactory wird im Container als bereichsbezogener Dienst registriert.

Die Standardimplementierung von IMiddlewareFactory, MiddlewareFactory, befindet sich im Paket Microsoft.AspNetCore.Http.

Zusätzliche Ressourcen

Bei IMiddlewareFactory/IMiddleware handelt es sich um einen Erweiterungspunkt für die Middleware-Aktivierung.

Die Erweiterungsmethode UseMiddleware überprüft, ob der registrierte Typ einer Middleware IMiddleware implementiert. Falls dies der Fall ist, wird die im Container registrierte IMiddlewareFactory-Instanz im Container verwendet, um die IMiddleware-Implementierung aufzulösen, anstatt die konventionsbasierte Middlewareaktivierungslogik zu verwenden. Die Middleware wird als bereichsbezogener oder vorübergehender Dienst im Dienstcontainer der App registriert.

Vorteile:

  • Aktivierung pro Clientanforderung (Injektion von bereichsbezogenen Diensten)
  • Starke Typisierung der Middleware

IMiddleware wird pro Clientanforderung (-verbindung) aktiviert, sodass bereichsbezogene Dienste in den Konstruktor der Middleware eingefügt werden können.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

IMiddleware

IMiddleware definiert Middleware für die Anforderungspipeline der App. Die InvokeAsync(HttpContext, RequestDelegate)-Methode verarbeitet Anforderungen und gibt einen Task zurück, der für die Ausführung der Middleware steht.

Über Konventionen aktivierte Middleware:

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

Über MiddlewareFactory aktivierte Middleware:

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

Für die Middleware werden Erweiterungen erstellt:

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

Es ist nicht möglich, Objekte mit UseMiddleware an eine Middleware zu übergeben, die über eine Factory aktiviert wurde:

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

Die Middleware, die über eine Factory aktiviert wurde, wird dem integrierten Container in Startup.ConfigureServices hinzugefügt:

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

    services.AddTransient<FactoryActivatedMiddleware>();

    services.AddRazorPages();
}

Beide Middlewares werden in der Anforderungsverarbeitungspipeline in Startup.Configure registriert:

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 stellt Methoden zur Verfügung, um die Middleware zu erstellen. Die Implementierung der Middlewarefactory wird im Container als bereichsbezogener Dienst registriert.

Die Standardimplementierung von IMiddlewareFactory, MiddlewareFactory, befindet sich im Paket Microsoft.AspNetCore.Http.

Zusätzliche Ressourcen

Bei IMiddlewareFactory/IMiddleware handelt es sich um einen Erweiterungspunkt für die Middleware-Aktivierung.

Die Erweiterungsmethode UseMiddleware überprüft, ob der registrierte Typ einer Middleware IMiddleware implementiert. Falls dies der Fall ist, wird die im Container registrierte IMiddlewareFactory-Instanz im Container verwendet, um die IMiddleware-Implementierung aufzulösen, anstatt die konventionsbasierte Middlewareaktivierungslogik zu verwenden. Die Middleware wird als bereichsbezogener oder vorübergehender Dienst im Dienstcontainer der App registriert.

Vorteile:

  • Aktivierung pro Clientanforderung (Injektion von bereichsbezogenen Diensten)
  • Starke Typisierung der Middleware

IMiddleware wird pro Clientanforderung (-verbindung) aktiviert, sodass bereichsbezogene Dienste in den Konstruktor der Middleware eingefügt werden können.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

IMiddleware

IMiddleware definiert Middleware für die Anforderungspipeline der App. Die InvokeAsync(HttpContext, RequestDelegate)-Methode verarbeitet Anforderungen und gibt einen Task zurück, der für die Ausführung der Middleware steht.

Über Konventionen aktivierte Middleware:

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

Über MiddlewareFactory aktivierte Middleware:

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

Für die Middleware werden Erweiterungen erstellt:

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

Es ist nicht möglich, Objekte mit UseMiddleware an eine Middleware zu übergeben, die über eine Factory aktiviert wurde:

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

Die Middleware, die über eine Factory aktiviert wurde, wird dem integrierten Container in Startup.ConfigureServices hinzugefügt:

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

    services.AddTransient<FactoryActivatedMiddleware>();

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

Beide Middlewares werden in der Anforderungsverarbeitungspipeline in Startup.Configure registriert:

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 stellt Methoden zur Verfügung, um die Middleware zu erstellen. Die Implementierung der Middlewarefactory wird im Container als bereichsbezogener Dienst registriert.

Die Standardimplementierung von IMiddlewareFactory, MiddlewareFactory, befindet sich im Paket Microsoft.AspNetCore.Http.

Zusätzliche Ressourcen