1

我使用asp.net mvc 4開發多租戶mvc應用程序。asp.net mvc 4控制器的依賴關係解析器

我正在使用Autofac作爲IOC容器,並且已經爲不同程序集中的每個客戶端配置了控制器。

根據當前的客戶端上下文,Autofac將根據當前的客戶端上下文切換出它返回哪個控制器,這通過查看路由數據來確定。

我得到一個異常

多種類型的發現匹配名爲「主頁」的控制器。

這看起來似乎表明Autofac正在返回多個匹配,但仔細觀察,似乎MVC甚至沒有爲控制器解析調用Autofac。

我可以看到一個呼叫,要求從DependencyResolverIControllerFactory,但從來沒有爲控制器本身。

是否需要實現我自己的控制器工廠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()返回多個名稱空間。

有沒有辦法解決這個問題?

+0

你的RouteDataTenantIdentificationStrategy是什麼樣子的,並且你在它裏面放置了一個斷點,看它是否在解析控制器時被調用? – 2013-02-18 04:27:43

+0

剛剛添加的話,會仔細檢查,看看它被稱爲 – 2013-02-18 04:55:37

+0

看來它被調用和返回正確的tenantid – 2013-02-18 05:03:35

回答

0

你必須在所有的路線,指定命名空間:

routes.MapRoute(
"Default",            // Route name 
    "{controller}/{action}/{id}",       // URL with parameters 
    new { controller = "Home", action = "Index", id = "" }, // Parameter defaults 
    "Some.NameSpace.To.Controllers" // required 
); 

如果你想在租戶DLL使用家居控制器:無論是從主站點HomeController重定向到它或者創建自定義路線(從Route繼承)並在其中執行命名空間選擇。

+0

那麼根據不同的應用,我不是想在主站點的dll使用控制器,或tenant1 DLL或其他租戶的dll的背景下,這個巨鼎它可能是最好寫我自己的控制器工廠,只是問依賴解析器給我的類型? – 2013-02-18 05:41:36

+0

我寧願使用自定義路線,因爲它是決定加載哪個控制器的路由。 ControllerFactory就是這樣:一個工廠構造了它所訂購的控制器。 – jgauffin 2013-02-18 06:27:47

+0

我可以動態覆蓋了命名空間中搜索定製路線? – 2013-02-18 06:32:41

相關問題