title: asp.net mvc 4 dependency resolver for controllers
body: <p>I'm using asp.net mvc 4 to develop a multi-tenant mvc application.</p>
  
  <p>I am using Autofac for the IOC container and have configured controllers to be registered for each client in different assemblies.</p>
  
  <p>Autofac will switch out which controller it returns when asked to resolve depending on the current client context, which is determineid by looking at the route data.</p>
  
  <p>I am getting an exception </p>
  
  <blockquote>
    <p>Multiple types were found that match the controller named 'Home'.</p>
  </blockquote>
  
  <p>Which would seem to indicate that Autofac is returning more than one match, however on closer inspection it seems that MVC is not even calling Autofac for controller resolution.</p>
  
  <p>I can see a call that asks for an <code>IControllerFactory</code> from the <code>DependencyResolver</code> but never for the controller itself.</p>
  
  <p>Do I need to implement my own controller factory ontop of using the dependency resolver?</p>
  
  <p>I have had a look through the source code of mvc and from what I can tell the <code>DefaultControllerFactory</code> uses the dependencyresolver and should resolve the controllers but I'm having trouble debugging into it to see exactly whats happenning.</p>
  
  <p>The tenant dlls are not referenced by the main website but copied in after build.</p>
  
  <p>My <code>global.asax</code> looks as follows:
      // First, create your application-level defaults using a standard
      // ContainerBuilder, just as you are used to.
      var builder = new ContainerBuilder();
      var appContainer = builder.Build();</p>
  
  <pre><code>// 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 =&gt; a.IsDefined(typeof (PluginAssemblyAttribute), false));
  
  
  foreach (var assembly in assemblies)
  {
      var pluginSpecification =
          assembly.GetCustomAttributes(typeof(PluginAssemblyAttribute), false)
              .OfType&lt;PluginAssemblyAttribute&gt;()
              .Single();
      var assembly1 = assembly;
      mtc.ConfigureTenant(pluginSpecification.Tenant, 
          b =&gt; b.RegisterControllers(assembly1));
  }
  
  DependencyResolver.SetResolver(new AutofacDependencyResolver(mtc));
  </code></pre>
  
  <p>The tenant identification strategy looks as follows:</p>
  
  <pre><code>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;
      }
  }
  </code></pre>
  
  <p>EDIT: The full exception is</p>
  
  <pre><code>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&amp; completedSynchronously) +114
  </code></pre>
  
  <p>Looking at this in more depth it would seem to indicate that this error happens because GetControllerTypeWithinNamespaces() is returning more than one namespace. </p>
  
  <p>Is there a way to overcome this?</p>