Я использую asp.net mvc 4 для разработки многопользовательского приложения mvc.
Я использую Autofac для контейнера IOC и настроил контроллеры для регистрации для каждого клиента в разных сборках.
Autofac переключит контроллер, который он возвращает, когда его попросят разрешить, в зависимости от текущего контекста клиента, который определяется путем просмотра данных маршрута.
я получаю исключение
Было найдено несколько типов, соответствующих контроллеру с именем «Дом».
Казалось бы, это указывает на то, что Autofac возвращает более одного совпадения, однако при ближайшем рассмотрении кажется, что MVC даже не вызывает Autofac для разрешения контроллера.
Я вижу вызов, который запрашивает IControllerFactory
от DependencyResolver
, но никогда не запрашивает сам контроллер.
Нужно ли мне реализовывать собственную фабрику контроллеров поверх использования преобразователя зависимостей?
Я просмотрел исходный код mvc и из того, что я могу сказать, DefaultControllerFactory
использует разрешение зависимостей и должен разрешать контроллеры, но у меня возникли проблемы с отладкой, чтобы точно увидеть, что происходит.
На DLL-файлы арендатора не ссылается основной веб-сайт, но они копируются после сборки.
Мой global.asax
выглядит следующим образом: // Во-первых, создайте параметры по умолчанию на уровне приложения с помощью стандартного // ContainerBuilder, как вы привыкли. var builder = новый 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() возвращает более одного пространства имен.
Есть ли способ преодолеть это?