我正在使用asp.net mvc 4开发多租户mvc应用程序。
我正在为IOC容器使用Autofac,并为不同程序集中的每个客户端配置了控制器。
当要求解决时,Autofac将根据当前客户端上下文切换出它返回的控制器,该客户端上下文是通过查看路由数据来确定的。
我收到了异常
发现多个类型与名为“Home”的控制器相匹配。
这似乎表明Autofac正在返回多个匹配,但仔细观察后,似乎MVC甚至没有调用Autofac来进行控制器分辨。
我可以看到一个来自IControllerFactory
的{{1}}来电,但从来没有要求控制器本身。
我是否需要在使用依赖项解析器的情况下实现我自己的控制器工厂?
我已经查看了mvc的源代码,并且我可以告诉DependencyResolver
使用依赖解析器并且应该解析控制器但是我无法调试它以查看到底发生了什么。< / p>
租户dll不会被主网站引用,而是在构建后复制。
我的DefaultControllerFactory
看起来如下:
//首先,使用标准创建应用程序级默认值
// ContainerBuilder,就像你习惯的那样。
var builder = new ContainerBuilder();
var appContainer = builder.Build();
global.asax
租户识别策略如下:
// 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;
}
}
更深入地看一下这似乎表明发生了这个错误,因为GetControllerTypeWithinNamespaces()返回了多个命名空间。
有没有办法克服这个问题?
答案 0 :(得分: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
继承)并在它