我使用asp.net mvc 4開發多租戶mvc應用程序。asp.net mvc 4控制器的依賴關係解析器
我正在使用Autofac作爲IOC容器,並且已經爲不同程序集中的每個客戶端配置了控制器。
根據當前的客戶端上下文,Autofac將根據當前的客戶端上下文切換出它返回哪個控制器,這通過查看路由數據來確定。
我得到一個異常
多種類型的發現匹配名爲「主頁」的控制器。
這看起來似乎表明Autofac正在返回多個匹配,但仔細觀察,似乎MVC甚至沒有爲控制器解析調用Autofac。
我可以看到一個呼叫,要求從DependencyResolver
的IControllerFactory
,但從來沒有爲控制器本身。
是否需要實現我自己的控制器工廠ontop使用依賴關係解析器?
我已經看過mvc的源代碼,並且我可以告訴DefaultControllerFactory
使用dependencyresolver並且應該解析控制器,但是我在調試時遇到了麻煩,無法準確查看發生了什麼。
租戶dll沒有被主網站引用,但在構建之後被複制。
我的global.asax
如下所示: //首先,使用標準 // ContainerBuilder創建應用程序級默認值,就像您習慣的那樣。 var builder = new ContainerBuilder(); var appContainer = builder.Build();
// Once you've built the application-level default container, you
// need to create a tenant identification strategy. The details of this
// are discussed later on.
var tenantIdentifier = new RouteDataTenantIdentificationStrategy();
// Now create the multitenant container using the application
// container and the tenant identification strategy.
var mtc = new MultitenantContainer(tenantIdentifier, appContainer);
// Configure the overrides for each tenant by passing in the tenant ID
// and a lambda that takes a ContainerBuilder.
var assemblies = AppDomain.CurrentDomain.GetAssemblies()
.AsQueryable()
.Where(a => a.IsDefined(typeof (PluginAssemblyAttribute), false));
foreach (var assembly in assemblies)
{
var pluginSpecification =
assembly.GetCustomAttributes(typeof(PluginAssemblyAttribute), false)
.OfType<PluginAssemblyAttribute>()
.Single();
var assembly1 = assembly;
mtc.ConfigureTenant(pluginSpecification.Tenant,
b => b.RegisterControllers(assembly1));
}
DependencyResolver.SetResolver(new AutofacDependencyResolver(mtc));
租戶標識策略如下所示:
public class RouteDataTenantIdentificationStrategy
: ITenantIdentificationStrategy
{
public bool TryIdentifyTenant(out object tenantId)
{
tenantId = null;
var context = HttpContext.Current;
try
{
if (context == null || context.Request == null)
{
return false;
}
}
catch (HttpException)
{
// This will happen at application startup in MVC3
// integration since the ILifetimeScopeProvider tries
// to be resolved from the container at the point where
// a new AutofacDependencyResolver is created.
tenantId = null;
return false;
}
var routeData = RouteTable.Routes.GetRouteData(
new HttpContextWrapper(context));
if (routeData != null)
tenantId = routeData.Values.ContainsKey("tenant") ?
routeData.Values["tenant"] : null;
return tenantId != null;
}
}
編輯:完整的例外是
The request for 'Home' has found the following matching controllers:
MultiTenantViewEngine.Web.Controllers.HomeController
MultiTenantViewEngine.Web.Tenant1.Controllers.HomeController]
System.Web.Mvc.DefaultControllerFactory.GetControllerTypeWithinNamespaces(RouteBase route, String controllerName, HashSet`1 namespaces) +230
System.Web.Mvc.DefaultControllerFactory.GetControllerType(RequestContext requestContext, String controllerName) +833
System.Web.Mvc.DefaultControllerFactory.System.Web.Mvc.IControllerFactory.GetControllerSessionBehavior(RequestContext requestContext, String controllerName) +196
System.Web.Mvc.MvcRouteHandler.GetSessionStateBehavior(RequestContext requestContext) +267
System.Web.Mvc.MvcRouteHandler.GetHttpHandler(RequestContext requestContext) +61
System.Web.Mvc.MvcRouteHandler.System.Web.Routing.IRouteHandler.GetHttpHandler(RequestContext requestContext) +44
System.Web.Routing.UrlRoutingModule.PostResolveRequestCache(HttpContextBase context) +352
System.Web.Routing.UrlRoutingModule.OnApplicationPostResolveRequestCache(Object sender, EventArgs e) +144
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +239
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +114
更深入地在這看這似乎表明,這個錯誤發生因爲GetControllerTypeWithinNamespaces()返回多個名稱空間。
有沒有辦法解決這個問題?
你的RouteDataTenantIdentificationStrategy是什麼樣子的,並且你在它裏面放置了一個斷點,看它是否在解析控制器時被調用? – 2013-02-18 04:27:43
剛剛添加的話,會仔細檢查,看看它被稱爲 – 2013-02-18 04:55:37
看來它被調用和返回正確的tenantid – 2013-02-18 05:03:35