1

asp.net mvc 4 を使用してマルチテナント mvc アプリケーションを開発しています。

私は IOC コンテナに Autofac を使用しており、異なるアセンブリのクライアントごとにコントローラを登録するように構成しました。

Autofac は、現在のクライアント コンテキストに応じて、解決を求められたときに返すコントローラーを切り替えます。これは、ルート データを見て決定されます。

例外が発生しています

「Home」という名前のコントローラーに一致する複数のタイプが見つかりました。

これは、Autofac が複数の一致を返していることを示しているように見えますが、よく調べてみると、MVC はコントローラーの解決のために Autofac を呼び出していないようです。

IControllerFactoryfromを要求する呼び出しが表示されますDependencyResolverが、コントローラー自体は要求されません。

依存関係リゾルバーを使用する上で、独自のコントローラー ファクトリを実装する必要がありますか?

私は mvc のソースコードを調べましたDefaultControllerFactoryが、依存関係リゾルバーを使用していてコントローラーを解決する必要があることがわかりましたが、何が起こっているのかを正確に確認するためにデバッグするのに問題があります。

テナント dll はメインの Web サイトでは参照されませんが、ビルド後にコピーされます。

// 最初に、標準のglobal.asaxContainerBuilder を使用してアプリケーション レベルのデフォルトを作成します // 慣れているように。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() が複数の名前空間を返しているためにこのエラーが発生しているように見えます。

これを克服する方法はありますか?

4

1 に答える 1

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)、その中で名前空間の選択を行います。

于 2013-02-18T05:32:51.273 に答える