Kích hoạt Middleware với Container Bên Thứ Ba trong ASP.NET Core
Bài viết này trình bày cách sử dụng IMiddlewareFactory và IMiddleware như một điểm mở rộng cho việc kích hoạt middleware (phần mềm trung gian) với container bên thứ ba. Để biết thông tin cơ bản về IMiddlewareFactory và IMiddleware, xem Kích hoạt Middleware dựa trên Factory trong ASP.NET Core.
Ứng dụng mẫu minh họa việc kích hoạt middleware bởi một cài đặt IMiddlewareFactory, SimpleInjectorMiddlewareFactory. Mẫu sử dụng container dependency injection (DI - tiêm phụ thuộc) Simple Injector.
Cài đặt middleware của mẫu ghi lại giá trị được cung cấp bởi một tham số query string (key). Middleware sử dụng một database context được tiêm vào (một service scoped) để ghi lại giá trị query string vào cơ sở dữ liệu in-memory.
Ứng dụng mẫu sử dụng Simple Injector chỉ cho mục đích minh họa. Việc sử dụng Simple Injector không phải là sự chứng thực. Các cách tiếp cận kích hoạt middleware được mô tả trong tài liệu và các vấn đề GitHub của Simple Injector được khuyến nghị bởi những người duy trì Simple Injector.
IMiddlewareFactory
IMiddlewareFactory cung cấp các phương thức để tạo middleware.
Trong ứng dụng mẫu, một middleware factory được cài đặt để tạo một instance SimpleInjectorActivatedMiddleware. Middleware factory sử dụng container Simple Injector để resolve middleware:
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 định nghĩa middleware cho request pipeline của ứng dụng.
Middleware được kích hoạt bởi một cài đặt IMiddlewareFactory (Middleware/SimpleInjectorActivatedMiddleware.cs):
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);
}
}Một extension được tạo cho middleware (Middleware/MiddlewareExtensions.cs):
public static class MiddlewareExtensions
{
public static IApplicationBuilder UseSimpleInjectorActivatedMiddleware(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<SimpleInjectorActivatedMiddleware>();
}
}Startup.ConfigureServices phải thực hiện một số tác vụ:
- Thiết lập container Simple Injector.
- Đăng ký factory và middleware.
- Cung cấp database context của ứng dụng từ container Simple Injector.
private Container _container = new Container();
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();
}Middleware được đăng ký trong request processing pipeline trong Startup.Configure:
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();
});
}