0

_ __ _ _______更新_____ _ __ _ ___ _ _ _ _

カスタムControllerFactoryの問題を解決するために、別の角度からアプローチしました。以下の回答を参照してください。

_ _______質問_____ _ __ _ _

複数のブランド展開に使用されるMVCコードベースがあります。各クライアントの要求を満たすために、オーバーライド可能なコントローラーとビューを設定しました。

ルート登録は次のようになります

protected void Application_Start()
    {
        string deploymentName = GetDeploymentName();
        RouteConfig.RegisterRoutes(RouteTable.Routes, deploymentName);
    }

RegisterRoutes内で、最初にデプロイメント名前空間で一致するコントローラーを探します。見つからない場合は、ベース名前空間を探します。

これは、展開ごとに個別のIISアプリケーションが設定されている場合は正常に機能します。これは、展開ごとに独自のApplication_Start()が実行されるためです。

ただし、1つのIISサイトインスタンスですべての展開を実行しようとしています。つまり、Application_Start()は1回だけ呼び出され、最初のデプロイメントでのみルートが登録されてヒットします。

RegisterRoutesをApplication_Start()からSession_Start()やApplication_PreRequestHandlerExecute()のようなものに移動しようとしています

protected void Application_PreRequestHandlerExecute()
    {
        string deploymentName = GetDeploymentName();

        using (RouteTable.Routes.GetWriteLock())
        {
            RouteTable.Routes.Clear();
            RouteConfig.RegisterRoutes(RouteTable.Routes, deploymentName);
        }
    }

このコードを使用すると、各リクエストは現在のデプロイメント名前空間を取得し、ルートテーブルをクリアして、新しい名前空間を使用してルートを再登録します。

2つの問題:

1:以前のルートが何であれ、リクエストは引き続き実行されます。したがって、この時点での要求はすでに特定のコントローラーとアクションに向けられているため、私はライフサイクルの間違った部分にいます。

2:次のリクエストは例外をスローします:

例外の詳細:System.InvalidOperationException:「ホーム」という名前のコントローラーに一致する複数のタイプが見つかりました。これは、このリクエストを処理するルート('{controller} / {action} / {id}')が、リクエストに一致するコントローラーを検索するための名前空間を指定していない場合に発生する可能性があります。この場合は、「namespaces」パラメーターを受け取る「MapRoute」メソッドのオーバーロードを呼び出して、このルートを登録します。

以前のルートの登録を解除しましたが、アプリケーションは以前に登録したコントローラーにハングアップしているようです。同じ名前の別のコントローラーに別のルートを登録したため、2つのコントローラーの間にあいまいさがあります。

私の2つの主な質問は次のとおりです。

1.リクエストが既存のルートに解決される前に新しいルートを登録するために使用できるApplication_Start()以外のライフサイクルイベントはありますか?

2.以前に登録したコントローラーであいまいな例外が発生しないように、ルートとコントローラーを完全にクリアするにはどうすればよいですか。

4

2 に答える 2

2

私はこれをすべて間違って行っていました...ルートについて心配する必要はありません。コントローラーのインスタンス化について心配する必要があります。Application_Start()でcontrollerFactoryを独自のカスタムファクトリに置き換えることができることがわかりました。

ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory(domainNamespaces));

そこで、ここでは、名前空間値を持つドメインキーのディクショナリをカスタムコントローラーファクトリのコンストラクターに渡します。

次に、ファクトリで、コントローラーのタイプを検索するメソッドをオーバーライドします

public class CustomControllerFactory : DefaultControllerFactory
{
    public Dictionary<string, string> DomainNamespaces { get; set; }

    public CustomControllerFactory(Dictionary<string, string> domainNamespaces)
        : base()
    {
        DomainNamespaces = domainNamespaces;
    }

    protected override Type GetControllerType(RequestContext requestContext, string controllerName)
    {

        controllerName += controllerName.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) ? String.Empty : "Controller";

        string requestDomain = requestContext.HttpContext.Request.Url.Host;
        string defaultNamespace = "API.Controllers.Base";
        string deploymentNamespace = "API.Controllers.Deployments." + DomainNamespaces[requestDomain];

        Assembly asm = Assembly.GetExecutingAssembly();
        Type deploymentMatch = null;
        Type defaultMatch = null;

        foreach (Type type in asm.GetTypes())
        {
            if (type.Namespace == deploymentNamespace && type.Name.Equals(controllerName, StringComparison.OrdinalIgnoreCase))
            {
                deploymentMatch = type;
            }
            else if (type.Namespace == defaultNamespace && type.Name.Equals(controllerName, StringComparison.OrdinalIgnoreCase))
            {
                defaultMatch = type;
            }
        }


        return deploymentMatch ?? defaultMatch;
    }
}
于 2012-08-16T17:59:07.883 に答える
1

すべてを1つのインスタンスで実行し、2人のユーザーがセッションを開いている場合、両方がサイトを閲覧しているため、どちらのルートを登録したままにする必要がありますか?

コンテキストが変更されたときに新しいルートを登録する代わりに、現在のコンテキストを処理するカスタムルートを作成できます。MVC3は、要求パラメーターに基づいて異なるコントローラーを使用します。

于 2012-08-16T15:36:07.020 に答える