2009-10-28 15 views
12

MVC 2プレビュー2では、AreaRegistrationが各エリアのルートを任意の順序でロードしていることに気付きました。もう一方を手に入れるには良い方法がありますか?MVC 2 AreaRegistration Routes注文

たとえば、「サイト」と「管理者」の2つの領域があります。どちらも "ブログ"コントローラを持っています。

私は次のようになる:

/admin/ --> go to Admin's Blog controller 
/  --> go to Site's Blog controller. 

問題は、それが最初のサイトのルートをロードしているということですので、私はURLに行くときには、「/管理/」ではなくadmin/{controller}/{action}/{id}{controller}/{action}/{id}に一致しています。 「サイト」領域に管理者コントローラがないため、404を取得します。

両方の領域のデフォルトは「ブログ」コントローラです。私は単純にURLとしてsite/{controller}/...を入れることができることを理解していますが、可能であれば根元に置いています。私はまた、グローバルRegisterRoutes関数でデフォルトルートを維持しようとしましたが、それは "サイト"領域に送信されません。

ありがとうございます!

答えて

7

現在、地域を発注することはできません。しかし、私は、各エリアをできるだけ他のエリアから独立させて秩序が重要でないようにしようとするのは意味があると思います。

たとえば、デフォルトの{controller}/{action}/{id}ルートを使用する代わりに、各コントローラの特定のルートに置き換えることができます。または、そのデフォルトルートに制約を追加します。

私たちは注文を許可するオプションを検討していますが、機能を過度に複雑にしたくありません。

+0

Hey Phil、説明のために感謝します。 私はエリアから自分の「サイト」を移動させてしまい、現在は「デフォルト/非エリア」セクション(ルートにビューとコントローラがあります)です。私は "あいまいなコントローラ"エラーを避けるために、デフォルトのコントローラに私の名前空間のパラメータを設定しました。 また、サイト領域ルートの管理者を無視するために、制約を^((?! admin)。*)に設定している可能性があります。 mvc 1(非エリア)ルートが潜在的にオーダーに大きく依存しているように見えますが、複雑さはそれほど大きくないことに同意します。 ありがとう! – Jason

+0

ルーティングプロセスは通常、ルールの順序に依存するため、「順序付け」機能が重要になる場合があります。 – twk

+0

地域の登録(そしてそのルート)を任意の順序で注文できる2つのテクニックについては、私の回答を参照してください。 – Eilon

30

Haackedが言ったこととは別に、エリア登録(およびルート)を注文することは非常に可能です。あなたがしなければならないのは、どのような順序であれ、手動で各エリアを登録するだけです。 RegisterAllAreas()を呼び出すのと同じくらい滑らかではありませんが、間違いなく実行可能です。

protected void Application_Start() { 
    var area1reg = new Area1AreaRegistration(); 
    var area1context = new AreaRegistrationContext(area1reg.AreaName, RouteTable.Routes); 
    area1reg.RegisterArea(area1context); 

    var area2reg = new Area2AreaRegistration(); 
    var area2context = new AreaRegistrationContext(area2reg.AreaName, RouteTable.Routes); 
    area2reg.RegisterArea(area2context); 

    var area3reg = new Area3AreaRegistration(); 
    var area3context = new AreaRegistrationContext(area3reg.AreaName, RouteTable.Routes); 
    area3reg.RegisterArea(area3context); 
} 

別のオプションは、)(RegisterAllAreasのコードを取る、独自のアプリにそれをコピーして、順序を決定するための独自のメカニズムを構築することです。ビルトインメソッドがしているすばらしいキャッシングロジックがすべて必要な場合はコピーするのはかなりコードですが、アプリでもそれが必要ない場合もあります。

AreaUtils.csのGlobal.asaxで

using System; 
    using System.Web.Mvc; 
    using System.Web.Routing; 

    namespace SledgeHammer.Mvc.Site 
    { 
     public static class Utils 
     { 
       public static void RegisterArea<T>(RouteCollection routes, 
    object state) where T : AreaRegistration 

      { 
       AreaRegistration registration = 
    (AreaRegistration)Activator.CreateInstance(typeof(T)); 

        AreaRegistrationContext context = 
    new AreaRegistrationContext(registration.AreaName, routes, state); 

        string tNamespace = registration.GetType().Namespace; 
        if (tNamespace != null) 
       { 
        context.Namespaces.Add(tNamespace + ".*"); 
       } 

       registration.RegisterArea(context); 
      } 
     } 

    } 

:生成されたエリア登録コードに

Utils.RegisterArea<SystemAreaRegistration>(RouteTable.Routes, null); 
Utils.RegisterArea<ClientSitesAreaRegistration>(RouteTable.Routes, null); 

//AreaRegistration.RegisterAllAreas(); do not dublicate register areas 

ませrequred変更

+0

偉大な答え。また、メソッドを作成するとコードが少なくなり、メソッドが1つのコード行になります。 – CRice

4

私はこのソリューションを作ります。 私はまた、リクエストでドメインのタイプ(システムドメインまたはユーザサイト)でルートをフィルタリングするために、ルートでカスタムconstrantを使用します。

これは一例として、私の地域の登録です:あなただけの特定の領域/コントローラにあなたをルートをマップする際の基準については

namespace SledgeHammer.MVC.Site.Areas.System 
{ 
    public class SystemAreaRegistration : AreaRegistration 
    { 
     public override string AreaName 
     { 
      get { return "System"; } 
     } 

     public override void RegisterArea(AreaRegistrationContext context) 
     { 
      context.MapRoute(
       "System_Feedback", 
       "Feedback", 
       new { controller = "Feedback", action = "Index" } 
      ); 
      context.MapRoute(
       "System_Information", 
       "Information/{action}/{id}", 
       new { controller = "Information", action = "Index", id = UrlParameter.Optional } 
      ); 
     } 
    } 
} 



namespace SledgeHammer.MVC.Site.Areas.ClientSites 
{ 
    public class ClientSitesAreaRegistration : AreaRegistration 
    { 
     public override string AreaName 
     { 
      get { return "ClientSites"; } 
     } 

     public override void RegisterArea(AreaRegistrationContext context) 
     { 
      context.MapRoute(
       "ClientSites_default", 
       "{controller}/{action}/{id}", 
       new { controller = "Site", action = "Index", id = UrlParameter.Optional }, 
       new { Host = new SiteInGroups("clients") } 
      ); 
     } 
    } 
} 
+0

utilクラスは、エリアの名前空間を追加する必要があることを指摘しているのですばらしいです。それ以外の場合は、コントローラとコントローラはリンクされません。 –

4

、MVC3で

(MVC2のことは知りません)単にグローバルルートを使用することができます。 名前空間/領域を指定してください。

routes.MapRoute(
     "CatchRoot", "", 
     new { controller = "SITEBLOG-CONTROLLER-NAME", action = "Index"} 
    ).DataTokens.Add("area", "SITE-AREA-NAME"); 
+0

+1 - これはすべてを1つのエリアにグループ化できるよりクリーンなURLでキャッチオールとして機能する領域。 –

+0

完璧に動作します! 「特別なもの」と実際の領域の代わりに、すべてのコントローラを領域に入れることができます。誰もが同じものを望むなら、ルートconfigにデフォルトルートを登録してください。 – FDIM