我刚刚做了一个练习,试图做到这一点。不幸的是,没有办法在启动后直接将中间件注入到基于 Katana 的主机中。这样做的原因是,为了实际使用中间件,它必须组合成application delegate。 Katana 的实现通过调用IAppBuilder.Build(typeof(AppFunc)) 来实现这一点,其中AppFunc 是应用程序委托的指定类型的使用别名:初始化完成时Func<IDictionary<string,object>, Task>。这是.Initialize底部的关键行:
AppFunc = (AppFunc)builder.Build(typeof(AppFunc));
您必须配置中间件的唯一机会是在此之前,在您编写的启动类的配置步骤中或通过web.config。
为了清楚说明什么行不通,我正在尝试这样的事情:
public class Startup
{
public void Configuration(IAppBuilder app)
{
HomeController.Initialized += () => ConfigureGoogle(app);
}
private void ConfigureGoogle(IAppBuilder app)
{
app.UseGoogleAuthentication(/* stuff */);
}
}
public class HomeController : Controller
{
public event EventHandler Initialized;
[Route("/setup/submit"), AcceptVerbs(HttpVerbs.Post)]
public ActionResult SetupSubmit()
{
/* ... */
Initialized();
}
}
这不会引发异常,也没有明显的错误迹象 - 但它不起作用,因为此时应用程序委托已经组成。 Katana 没有为您提供任何用于重新构建应用程序委托的 API(而且我不确定这是否是一个好主意 - 这种机制可能会产生无数错误;例如,应该如何服务器在初始化后重构应用程序委托时处理正在进行的请求?)。
你的选择是什么? @DavidFahlander 的方法将是正确的方法,但如果你想获得活力,你仍然需要小心。看看.MapWhen 做了什么:
// put middleware in pipeline before creating branch
var options = new MapWhenOptions { Predicate = predicate };
IAppBuilder result = app.Use<MapWhenMiddleware>(options);
// create branch and assign to options
IAppBuilder branch = app.New();
configuration(branch);
options.Branch = (AppFunc)branch.Build(typeof(AppFunc));
首先,请注意,这会使用 MapWhenMiddleware 类型调用 app.Use。这意味着您面临与以前相同的限制 - 这一切都必须预先完成。分支中间件也将在初始化完成之前被烘焙:见最后一行:branch.Build。
您在这里获得活力的唯一希望是以实现目标的方式使用谓词。这不会让你 100% 到达那里,但它会非常接近:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapWhen(ctx => ClientHasWsFederationConfigured() && ctx.Request.Headers.Get("Host").Equals("customer1.cloudservice.net"), app2 =>
{
app2.UseWsFederationAuthentication(...);
});
app.MapWhen(ctx => ClientHasGoogleAuthConfigured() && ctx.Request.Headers.Get("Host").Equals("customer2.cloudservice.net"), app2 =>
{
app2.UseGoogleAuthentication(...);
});
}
}
这里的限制如下:
- 您必须预先配置所有支持的身份验证类型。您无法在应用运行时添加新的。
-
ClientHasXXXConfigured 将在每个请求上运行。根据您的工作,这可能会或可能不会被接受。
鉴于您在问题中提供的信息,我认为这些权衡可能是可以的,只要您注意 ClientHasXXXConfigured(或其等效项)的作用。