Factorybezogene Middlewareaktivierung in ASP.NET CoreFactory-based middleware activation in ASP.NET Core

Bei IMiddlewareFactory/IMiddleware handelt es sich um einen Erweiterungspunkt für die Middleware-Aktivierung.IMiddlewareFactory/IMiddleware is an extensibility point for middleware activation.

Die Erweiterungsmethode UseMiddleware überprüft, ob der registrierte Typ einer Middleware IMiddleware implementiert.UseMiddleware extension methods check if a middleware's registered type implements IMiddleware. 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.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. Die Middleware wird als bereichsbezogener oder vorübergehender Dienst im Dienstcontainer der App registriert.The middleware is registered as a scoped or transient service in the app's service container.

Vorteile:Benefits:

  • Aktivierung pro Clientanforderung (Injektion von bereichsbezogenen Diensten)Activation per client request (injection of scoped services)
  • Starke Typisierung der MiddlewareStrong typing of middleware

IMiddleware wird pro Clientanforderung (-verbindung) aktiviert, sodass bereichsbezogene Dienste in den Konstruktor der Middleware eingefügt werden können.IMiddleware is activated per client request (connection), so scoped services can be injected into the middleware's constructor.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)View or download sample code (how to download)

IMiddlewareIMiddleware

IMiddleware definiert Middleware für die Anforderungspipeline der App.IMiddleware defines middleware for the app's request pipeline. Die InvokeAsync(HttpContext, RequestDelegate)-Methode verarbeitet Anforderungen und gibt einen Task zurück, der für die Ausführung der Middleware steht.The InvokeAsync(HttpContext, RequestDelegate) method handles requests and returns a Task that represents the execution of the middleware.

Über Konventionen aktivierte Middleware: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);
    }
}

Über MiddlewareFactory aktivierte Middleware: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);
    }
}

Für Middlewares werden Erweiterungen erstellt: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>();
    }
}

Es ist nicht möglich, Objekte mit UseMiddleware an eine Middleware zu übergeben, die über eine Factory aktiviert wurde: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);
}

Die Middleware, die über eine Factory aktiviert wurde, wird dem integrierten Container in Startup.ConfigureServices hinzugefügt: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();
}

Beide Middlewares werden in der Anforderungsverarbeitungspipeline in Startup.Configure registriert: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 stellt Methoden zur Verfügung, um die Middleware zu erstellen.IMiddlewareFactory provides methods to create middleware. Die Implementierung der Middlewarefactory wird im Container als bereichsbezogener Dienst registriert.The middleware factory implementation is registered in the container as a scoped service.

Die Standardimplementierung von IMiddlewareFactory, MiddlewareFactory, befindet sich im Paket Microsoft.AspNetCore.Http.The default IMiddlewareFactory implementation, MiddlewareFactory, is found in the Microsoft.AspNetCore.Http package.

Bei IMiddlewareFactory/IMiddleware handelt es sich um einen Erweiterungspunkt für die Middleware-Aktivierung.IMiddlewareFactory/IMiddleware is an extensibility point for middleware activation.

Die Erweiterungsmethode UseMiddleware überprüft, ob der registrierte Typ einer Middleware IMiddleware implementiert.UseMiddleware extension methods check if a middleware's registered type implements IMiddleware. 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.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. Die Middleware wird als bereichsbezogener oder vorübergehender Dienst im Dienstcontainer der App registriert.The middleware is registered as a scoped or transient service in the app's service container.

Vorteile:Benefits:

  • Aktivierung pro Clientanforderung (Injektion von bereichsbezogenen Diensten)Activation per client request (injection of scoped services)
  • Starke Typisierung der MiddlewareStrong typing of middleware

IMiddleware wird pro Clientanforderung (-verbindung) aktiviert, sodass bereichsbezogene Dienste in den Konstruktor der Middleware eingefügt werden können.IMiddleware is activated per client request (connection), so scoped services can be injected into the middleware's constructor.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)View or download sample code (how to download)

IMiddlewareIMiddleware

IMiddleware definiert Middleware für die Anforderungspipeline der App.IMiddleware defines middleware for the app's request pipeline. Die InvokeAsync(HttpContext, RequestDelegate)-Methode verarbeitet Anforderungen und gibt einen Task zurück, der für die Ausführung der Middleware steht.The InvokeAsync(HttpContext, RequestDelegate) method handles requests and returns a Task that represents the execution of the middleware.

Über Konventionen aktivierte Middleware: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);
    }
}

Über MiddlewareFactory aktivierte Middleware: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);
    }
}

Für Middlewares werden Erweiterungen erstellt: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>();
    }
}

Es ist nicht möglich, Objekte mit UseMiddleware an eine Middleware zu übergeben, die über eine Factory aktiviert wurde: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);
}

Die Middleware, die über eine Factory aktiviert wurde, wird dem integrierten Container in Startup.ConfigureServices hinzugefügt: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);
}

Beide Middlewares werden in der Anforderungsverarbeitungspipeline in Startup.Configure registriert: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 stellt Methoden zur Verfügung, um die Middleware zu erstellen.IMiddlewareFactory provides methods to create middleware. Die Implementierung der Middlewarefactory wird im Container als bereichsbezogener Dienst registriert.The middleware factory implementation is registered in the container as a scoped service.

Die Standardimplementierung von IMiddlewareFactory, MiddlewareFactory, befindet sich im Paket Microsoft.AspNetCore.Http.The default IMiddlewareFactory implementation, MiddlewareFactory, is found in the Microsoft.AspNetCore.Http package.

Zusätzliche RessourcenAdditional resources