_ __ _ __ _ ____更新__ _ __ _ __ _ ___
从不同的角度使用自定义 ControllerFactory 解决问题,请参见下面的答案。
_ __ _ ____原始问题__ _ __ _ __
我有一个用于多个品牌部署的 MVC 代码库。为了满足每个客户的需求,我们设置了可覆盖的控制器和视图。
路线注册看起来像这样
protected void Application_Start()
{
string deploymentName = GetDeploymentName();
RouteConfig.RegisterRoutes(RouteTable.Routes, deploymentName);
}
在 RegisterRoutes 中,我们首先在部署命名空间中寻找匹配的控制器,如果没有找到,则在基本命名空间中查找。
如果我们为每个部署都设置了单独的 IIS 应用程序,这可以正常工作,因为每个部署都会执行自己的 Application_Start()
但是,我们正在尝试在一个 IIS 站点实例中运行所有部署。这意味着 Application_Start() 只被调用一次,只为第一次部署注册路由。
我正在尝试将 RegisterRoutes 从 Application_Start() 移至 Session_Start() 或 Application_PreRequestHandlerExecute()
protected void Application_PreRequestHandlerExecute()
{
string deploymentName = GetDeploymentName();
using (RouteTable.Routes.GetWriteLock())
{
RouteTable.Routes.Clear();
RouteConfig.RegisterRoutes(RouteTable.Routes, deploymentName);
}
}
使用此代码,每个请求都会获取当前部署命名空间,清除路由表,并使用新命名空间再次注册路由。
2个问题:
1:请求仍然根据之前的路由执行。所以我在生命周期的错误部分,因为此时的请求已经注定了特定的控制器和操作。
2:下一个请求会抛出异常:
异常详细信息:System.InvalidOperationException:找到与名为“Home”的控制器匹配的多种类型。如果服务此请求的路由 ('{controller}/{action}/{id}') 未指定命名空间来搜索与请求匹配的控制器,则可能会发生这种情况。如果是这种情况,请通过调用采用“namespaces”参数的“MapRoute”方法的重载来注册此路由。
即使我取消了之前注册的路由,应用程序似乎仍然挂在之前注册的控制器上,现在我已经注册了另一个到另一个同名控制器的路由,这两个控制器之间存在歧义。
我的两个主要问题是:
1. 除了 Application_Start() 之外,是否还有其他生命周期事件可用于在请求已解析为先前存在的路由之前注册新路由?
2. 如何彻底清除路由和控制器,以免之前注册的控制器出现歧义异常?