在ASP.Net Core中在运行时安装新的中间件 [英] Installing a new middleware at runtime in ASP.Net Core
问题描述
当我的应用程序启动时,我有一堆模块(module1,module2…).对于每个模块,我都有很多控制器动作:
When my application starts, I have a bunch of modules (module1, module2 …). For each of this module I have a bunch of controller actions :
/myModuleController/module1/action1
/myModuleController/module1/action2
/myModuleController/module2/action1
/myModuleController/module2/action2
…
由于用户每个模块可以登录一次,因此我为每个模块部署了一个身份验证中间件,方法很简单:
As the user can log himself once per module, I deploy an authentication middleware per module, which is simply done this way :
app.UseWhen((context) => context.Request.Path.StartsWithSegments(urlPath), appbuilder =>
{
appbuilder.UseCookieAuthentication(new CookieAuthenticationOptions()
{
CookieName = cookieName,
…
});
});
因此,基本上,在url路径/myModuleController/module1
上,我有一个中间件加它的cookie,还有一个用于/myModuleController/module2
的中间件……这有点不寻常,但它工作正常,我对此行为感到满意.
So basically, on the url path /myModuleController/module1
I have one middleware plus its cookie, another for /myModuleController/module2
… It’s a bit unusual I guess but it’s working fine, I’m happy with the behavior.
问题来了:我希望能够在运行时添加一个新模块,这意味着能够使用app.UseWhen(url, app. UseCookieAuthentication(…))
之类的代码来部署新的中间件.我天真地尝试将IApplicationBuilder app
注入负责添加模块的控制器中,但出现异常:
Here come the issue : I want to be able to add a new module at runtime, which would imply to be able to deploy a new middleware with a piece of code like app.UseWhen(url, app. UseCookieAuthentication(…))
. I tried naively to inject IApplicationBuilder app
in the controller responsible for the addition of the module, but I’m getting an exception:
System.InvalidOperationException:尝试激活"AdminController"时无法解析类型为"Microsoft.AspNetCore.Builder.IApplicationBuilder"的服务
System.InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Builder.IApplicationBuilder' while attempting to activate 'AdminController'
我对您的问题是:它应该可以工作,并且我必须在某个地方犯了一个错误吗?或者,您是否清楚我在这里尝试的工作没有机会?
My question to you is : should it be working and I must have made a mistake somewhere? or, is it clear to you that what I’m trying here had not chance to work?
您将如何达到相同的要求? 谢谢.
How would you have achieved the same requirement ? Thanks.
推荐答案
首先,我们需要一项服务来保持运行时中间件配置
Firstly we need a service to keep the runtime middleware configurations
public class RuntimeMiddlewareService
{
private Func<RequestDelegate, RequestDelegate> _middleware;
private IApplicationBuilder _appBuilder;
internal void Use(IApplicationBuilder app)
=> _appBuilder = app.Use(next => context => _middleware == null ? next(context) : _middleware(next)(context));
public void Configure(Action<IApplicationBuilder> action)
{
var app = _appBuilder.New();
action(app);
_middleware = next => app.Use(_ => next).Build();
}
}
然后添加一些扩展方法以在Startup
Then add some extension methods to use it in Startup
public static class RuntimeMiddlewareExtensions
{
public static IServiceCollection AddRuntimeMiddleware(this IServiceCollection services, ServiceLifetime lifetime = ServiceLifetime.Singleton)
{
services.Add(new ServiceDescriptor(typeof(RuntimeMiddlewareService), typeof(RuntimeMiddlewareService), lifetime));
return services;
}
public static IApplicationBuilder UseRuntimeMiddleware(this IApplicationBuilder app, Action<IApplicationBuilder> defaultAction = null)
{
var service = app.ApplicationServices.GetRequiredService<RuntimeMiddlewareService>();
service.Use(app);
if (defaultAction != null)
{
service.Configure(defaultAction);
}
return app;
}
}
然后修改您的Startup
添加到ConfigureServices
:
services.AddRuntimeMiddleware(/* ServiceLifetime.Scoped could be specified here if needed */);
添加到运行时指定的中间件应位于Configure
内部的位置.
Add to where the runtime specified middlewares should be inside Configure
.
app.UseRuntimeMiddleware(runtimeApp =>
{
//runtimeApp.Use...
//Configurations here could be replaced during the runtime.
});
最后,您可以从应用程序的其他部分重新配置运行时中间件
Finally, you could reconfigure the runtime middlewares from other parts of the application
//var runtimeMiddlewareService = serviceProvider.GetRequiredService<RuntimeMiddlewareService>();
//Or resolved via constructor.
runtimeMiddlewareService.Configure(runtimeApp =>
{
//runtimeApp.Use...
//Configurations here would override the former ones.
});
这篇关于在ASP.Net Core中在运行时安装新的中间件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!