ソースの分析——ASP.Net MVCの中で、Global.asaxの中でどのようにArea内部を指すデフォルトのRouteを配置しますか?

4290 ワード

ASP.Net MVCにRouteを設定するとデフォルトのRouteを設定できます.たとえば私は入力します.http://localhostに入るときはデフォルトで入力します.http://localhost/home/index.Global.asaxでこのように配置できます.
 
            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );
は簡単ですよね.
 
しかし、もしあなたがデフォルト値をArea内部のController/アクションに指したいなら、どうすればいいですか? 
上の例をまねて、私はこうします.
MyAreaというaraを新たに作って、ルートを設定します.
 
 
            routes.MapRoute(
                "Default", // Route name
                "{area}{controller}/{action}/{id}", // URL with parameters
                new {area = "MyArea", controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );
にアリーナのセレクションを追加しました.いいですよね.
 
運転してみます.
結果はControllerの衝突で、スクリーンショットは以下の通りです.
源码分析——在ASP.Net MVC 中,如何在Global.asax中配置一个指向Area内部的默认Route..._第1张图片 
これは私達が配置したあの‘Area’が機能していないと説明しています.MVCのrouteはAreaをサポートしていませんでした.
MyArea Registrationのソースコードを見に来ました.
        public Route MapRoute(string name, string url, object defaults, object constraints, string[] namespaces) {
            if (namespaces == null && Namespaces != null) {
                namespaces = Namespaces.ToArray();
            }

            Route route = Routes.MapRoute(name, url, defaults, constraints, namespaces);
            route.DataTokens["area"] = AreaName;

            // disabling the namespace lookup fallback mechanism keeps this areas from accidentally picking up
            // controllers belonging to other areas
            bool useNamespaceFallback = (namespaces == null || namespaces.Length == 0);
            route.DataTokens["UseNamespaceFallback"] = useNamespaceFallback;

            return route;
        }
 それはMapRouteの時にnamespaceの制約を加えた.私たちも加えてみます.
     routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new {controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
                new[] { "WebArchDemo.Areas.MyArea.*" }  
            );
 はい、成功しました.でも、よく見てください.Viewが間違っています.それは意外にもやはりAreaの外のViewを探して、このAreaの下のViewではありません.
 私達はView Engineのソースコードの中で原因を探して、肝心なコードはViewを探している時の下のいくつかの文です.
string areaName = AreaHelpers.GetAreaName(controllerContext.RouteData);
bool usingAreas = !String.IsNullOrEmpty(areaName);
List viewLocations = GetViewLocations(locations, (usingAreas) ? areaLocations : null);
 View Engineはcontroller Conttext.RouteDataの中でArea Nameを探します.見つけたらAreaの中のViewを使います.そうでなければルートディレクトリの下のViewを使います.このArea NameはいつRouteDataの中に置いたのですか?
振り返ってみます.私の前に貼ってあるMyAreearegistrationのソースコードを見てください.
route.DataTokens["area"] = AreaName;
AreaのRouteを登録する時、このArea Nameを入れます.
 
この点が分かりました.私たちは引き続きrouteを登録するところを改造できます.
          var route =   routes.MapRoute(
                                "Default", // Route name
                                "{controller}/{action}/{id}", // URL with parameters
                                new {controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
                                new[] { "WebArchDemo.Areas.MyArea.*" }  
                            );

 route.DataTokens["area"] = "MyArea";
完全に正しいです.
 
実際のプロジェクトでは、Area内部の一つのアクションに対してデフォルトのrouteを直接指す可能性が低いです.でも特殊なシーンがあります.
このような特殊なシーンを実現する試みを通して、AReaRegistrationの動作原理を分析し、RouteとView EngineがAreaをどのように処理しているかを探ってみました.
MVCはできるだけ少なくフレームに侵入した場合に、Area機構のセットを実現することが見られます.