Middlewareaktivierung mit einem Drittanbietercontainer in ASP.NET Core

In diesem Artikel wird veranschaulicht, wie IMiddlewareFactory und IMiddleware als Erweiterungspunkt für die Aktivierung von Middleware mit einem Drittanbietercontainer verwendet werden. Einführende Informationen zu IMiddlewareFactory und IMiddleware finden Sie im Artikel Factorybezogene Middlewareaktivierung in ASP.NET Core.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

Die Beispiel-App stellt die Aktivierung von Middleware durch eine IMiddlewareFactory-Implementierung (SimpleInjectorMiddlewareFactory) dar. Das Beispiel verwendet den Dependency Injection-Container Simple Injector.

Die Middlewareimplementierungen in diesem Beispiel erfassen den Wert, der von einem Parameter für Abfragezeichenfolgen (key) angegeben wird. Die Middleware verwendet einen eingefügten Datenbankkontext (einen bereichsbezogenen Dienst), um den Abfragezeichenwert in einer speicherinternen Datenbank zu erfassen.

Hinweis

Die Beispiel-App verwendet Simple Injector ausschließlich zu Demonstrationszwecken. Die Verwendung von Simple Injector ist nicht verpflichtend. Die Ansätze für die Aktivierung von Middleware, die in der Dokumentation zu Simple Injector und in GitHub-Problemen beschrieben werden, werden von den Besitzern von Simple Injector empfohlen. Weitere Informationen finden Sie in der Dokumentation zu Simple Injector und im GitHub-Repository für Simple Injector.

IMiddlewareFactory

IMiddlewareFactory stellt Methoden zur Verfügung, um die Middleware zu erstellen.

In der Beispiel-App wird eine Middlewarefactory implementiert, um eine SimpleInjectorActivatedMiddleware-Instanz zu erstellen. Die Middlewarefactory verwendet den Simple Injector-Container, um die Middleware aufzulösen:

public class SimpleInjectorMiddlewareFactory : IMiddlewareFactory
{
    private readonly Container _container;

    public SimpleInjectorMiddlewareFactory(Container container)
    {
        _container = container;
    }

    public IMiddleware Create(Type middlewareType)
    {
        return _container.GetInstance(middlewareType) as IMiddleware;
    }

    public void Release(IMiddleware middleware)
    {
        // The container is responsible for releasing resources.
    }
}

IMiddleware

IMiddleware definiert Middleware für die Anforderungspipeline der App.

Middleware, die von einer IMiddlewareFactory-Implementierung (Middleware/SimpleInjectorActivatedMiddleware.cs) aktiviert wurde:

public class SimpleInjectorActivatedMiddleware : IMiddleware
{
    private readonly AppDbContext _db;

    public SimpleInjectorActivatedMiddleware(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 = "SimpleInjectorActivatedMiddleware", 
                    Value = keyValue
                });

            await _db.SaveChangesAsync();
        }

        await next(context);
    }
}

Eine Erweiterung (Middleware/MiddlewareExtensions.cs) wird für die Middleware erstellt:

public static class MiddlewareExtensions
{
    public static IApplicationBuilder UseSimpleInjectorActivatedMiddleware(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<SimpleInjectorActivatedMiddleware>();
    }
}

Startup.ConfigureServices muss mehrere Tasks durchführen:

  • Richten Sie den Simple Injector-Container ein.
  • Registrieren Sie die Factory und die Middleware.
  • Stellen Sie den Datenbankkontext der App über den Simple Injector-Container zur Verfügung.
public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    // Replace the default middleware factory with the 
    // SimpleInjectorMiddlewareFactory.
    services.AddTransient<IMiddlewareFactory>(_ =>
    {
        return new SimpleInjectorMiddlewareFactory(_container);
    });

    // Wrap ASP.NET Core requests in a Simple Injector execution 
    // context.
    services.UseSimpleInjectorAspNetRequestScoping(_container);

    // Provide the database context from the Simple 
    // Injector container whenever it's requested from 
    // the default service container.
    services.AddScoped<AppDbContext>(provider => 
        _container.GetInstance<AppDbContext>());

    _container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

    _container.Register<AppDbContext>(() => 
    {
        var optionsBuilder = new DbContextOptionsBuilder<DbContext>();
        optionsBuilder.UseInMemoryDatabase("InMemoryDb");
        return new AppDbContext(optionsBuilder.Options);
    }, Lifestyle.Scoped);

    _container.Register<SimpleInjectorActivatedMiddleware>();

    _container.Verify();
}

Die Middlewares wird in der Anforderungsverarbeitungspipeline in Startup.Configure registriert:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
    }

    app.UseSimpleInjectorActivatedMiddleware();

    app.UseStaticFiles();
    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

In diesem Artikel wird veranschaulicht, wie IMiddlewareFactory und IMiddleware als Erweiterungspunkt für die Aktivierung von Middleware mit einem Drittanbietercontainer verwendet werden. Einführende Informationen zu IMiddlewareFactory und IMiddleware finden Sie im Artikel Factorybezogene Middlewareaktivierung in ASP.NET Core.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)

Die Beispiel-App stellt die Aktivierung von Middleware durch eine IMiddlewareFactory-Implementierung (SimpleInjectorMiddlewareFactory) dar. Das Beispiel verwendet den Dependency Injection-Container Simple Injector.

Die Middlewareimplementierungen in diesem Beispiel erfassen den Wert, der von einem Parameter für Abfragezeichenfolgen (key) angegeben wird. Die Middleware verwendet einen eingefügten Datenbankkontext (einen bereichsbezogenen Dienst), um den Abfragezeichenwert in einer speicherinternen Datenbank zu erfassen.

Hinweis

Die Beispiel-App verwendet Simple Injector ausschließlich zu Demonstrationszwecken. Die Verwendung von Simple Injector ist nicht verpflichtend. Die Ansätze für die Aktivierung von Middleware, die in der Dokumentation zu Simple Injector und in GitHub-Problemen beschrieben werden, werden von den Besitzern von Simple Injector empfohlen. Weitere Informationen finden Sie in der Dokumentation zu Simple Injector und im GitHub-Repository für Simple Injector.

IMiddlewareFactory

IMiddlewareFactory stellt Methoden zur Verfügung, um die Middleware zu erstellen.

In der Beispiel-App wird eine Middlewarefactory implementiert, um eine SimpleInjectorActivatedMiddleware-Instanz zu erstellen. Die Middlewarefactory verwendet den Simple Injector-Container, um die Middleware aufzulösen:

public class SimpleInjectorMiddlewareFactory : IMiddlewareFactory
{
    private readonly Container _container;

    public SimpleInjectorMiddlewareFactory(Container container)
    {
        _container = container;
    }

    public IMiddleware Create(Type middlewareType)
    {
        return _container.GetInstance(middlewareType) as IMiddleware;
    }

    public void Release(IMiddleware middleware)
    {
        // The container is responsible for releasing resources.
    }
}

IMiddleware

IMiddleware definiert Middleware für die Anforderungspipeline der App.

Middleware, die von einer IMiddlewareFactory-Implementierung (Middleware/SimpleInjectorActivatedMiddleware.cs) aktiviert wurde:

public class SimpleInjectorActivatedMiddleware : IMiddleware
{
    private readonly AppDbContext _db;

    public SimpleInjectorActivatedMiddleware(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 = "SimpleInjectorActivatedMiddleware", 
                    Value = keyValue
                });

            await _db.SaveChangesAsync();
        }

        await next(context);
    }
}

Eine Erweiterung (Middleware/MiddlewareExtensions.cs) wird für die Middleware erstellt:

public static class MiddlewareExtensions
{
    public static IApplicationBuilder UseSimpleInjectorActivatedMiddleware(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<SimpleInjectorActivatedMiddleware>();
    }
}

Startup.ConfigureServices muss mehrere Tasks durchführen:

  • Richten Sie den Simple Injector-Container ein.
  • Registrieren Sie die Factory und die Middleware.
  • Stellen Sie den Datenbankkontext der App über den Simple Injector-Container zur Verfügung.
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    // Replace the default middleware factory with the 
    // SimpleInjectorMiddlewareFactory.
    services.AddTransient<IMiddlewareFactory>(_ =>
    {
        return new SimpleInjectorMiddlewareFactory(_container);
    });

    // Wrap ASP.NET Core requests in a Simple Injector execution 
    // context.
    services.UseSimpleInjectorAspNetRequestScoping(_container);

    // Provide the database context from the Simple 
    // Injector container whenever it's requested from 
    // the default service container.
    services.AddScoped<AppDbContext>(provider => 
        _container.GetInstance<AppDbContext>());

    _container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

    _container.Register<AppDbContext>(() => 
    {
        var optionsBuilder = new DbContextOptionsBuilder<DbContext>();
        optionsBuilder.UseInMemoryDatabase("InMemoryDb");
        return new AppDbContext(optionsBuilder.Options);
    }, Lifestyle.Scoped);

    _container.Register<SimpleInjectorActivatedMiddleware>();

    _container.Verify();
}

Die Middlewares wird in der Anforderungsverarbeitungspipeline in Startup.Configure registriert:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
    }

    app.UseSimpleInjectorActivatedMiddleware();

    app.UseStaticFiles();
    app.UseMvc();
}

Zusätzliche Ressourcen