2011-06-30 12 views
1

すべてのCMSページURLを単一コントローラ(PageController)とアクション(詳細)にマップしたいと思います。Asp.net mvc 3.0ツリー構造のページカスタムルーティング

これらすべてのURLをマッピングするカスタムルーティングを作成するにはどうすればよいですか?

/teacher 
/teacher/kindergarten 
/teacher/kindergarten/1 
/teacher/primary 
/teacher/primary/english 
/teacher/primary/language 
/teacher/primary/language/chinese 
/teacher/primary/math 
/teacher/primary/science 
/parent 
/parent/kindergarten 
/parent/primary1-3 
/parent/primary4-6 
/leader 
/leader/kindergarten 
/leader/kindergarten/1 

答えて

1

データベースでこれらのURLを持っている場合は、アプリケーションが起動したときにルートをマップすることができます:

var pages = siteDB.Pages.ToList(); 
    string pagePath = ""; 
    foreach (var page in pages) 
    { 
    routeVals = new RouteValueDictionary(); 
    constraints = new RouteValueDictionary(); 

    routeVals.Add("controller", "page"); 
    routeVals.Add("action", "details"); 

    constraints.Add("path", "[a-zA-Z0-9\\-]*"); 

    // any child pages? must add these routes before their parent pages. 
    var childPages = siteDB.Pages.Where(p => p.ParentPageId == page.PageId).ToList(); 
    foreach (var childPage in childPages) 
    { 
     pagePath = BuildPath(childPage); 
     RouteTable.Routes.Add(new Route(pagePath, new MvcRouteHandler()) 
     { 
     Defaults = routeVals, 
     Constraints = constraints, 
     DataTokens = 
      new RouteValueDictionary { 
      { "pageid", childPage.PageId }, 
      { "path", pagePath } 
      } 
     }); 

     // Any further child pages? (Only 3 levels supported) 
     var childSubPages = siteDB.Pages.Where(p => p.ParentPageId == childPage.PageId).ToList(); 
     foreach (var childSubPage in childSubPages) 
     { 
      pagePath = BuildPath(childSubPage); 
      RouteTable.Routes.Add(new Route(pagePath, new MvcRouteHandler()) 
      { 
       Defaults = routeVals, 
       Constraints = constraints, 
       DataTokens = 
        new RouteValueDictionary { 
       { "pageid", childSubPage.PageId }, 
       { "path", pagePath } 
       } 
      }); 
     } 
    } 

このコードは、それらが親IDによってリンクされているデータベースからページを取ります。

は、ここで各ページへの完全なパスを生成ビルドパス機能です:

public static string BuildPath(Page page) 
{ 
    if (page.ParentPageId == 1) 
    { 
    return page.PageKey; 
    } 
    else 
    { 
    SiteDataEntities siteDB = new SiteDataEntities(); 
    string path = page.PageKey; 
    Page parent = siteDB.Pages.Find(page.ParentPageId); 
    while (parent != null) 
    { 
     path = parent.PageKey + "/" + path; 
     parent = siteDB.Pages.Find(parent.ParentPageId); 
     if (parent.PageKey == "home") break; 
    } 
    return path; 
    } 
} 
+0

ありがとうSam、これは私が探しているものです。ありがとう=) – Zayar

+0

こんにちはサム、BuildPath関数は何ですか? – Zayar

+0

BuildPath関数と説明を追加しました。 –

1

前の提案された解決策は、ページのみの少量のために働いています。 コードに従って:

アプリケーションは、サイトページごとにルートを生成して登録します。結果として、私たちのサイトのページと少なくとも同じ量のルートがあります。

    :あなたはおそらく

    ... RouteModuleは最初の正しいものを見つけると、正しいハンドラ、コントローラ、アクション、ビューを実行するための経路によってそれらのそれぞれのルートをチェックする必要が知っているように、これを解決するために他の二つの方法があります。

  • あなたはRouteBaseから派生クラスを作成し、必要なプロパティとメソッドを実装することができます。セグメントに分割し、URL、確定現在のページpageidにしてRouteValueDictionaryを埋め、パス、両親など

  • あなたがcustom rewrite providerとUrlRewriteModuleをカスタマイズすることができます。 MVCデフォルトルートにツリーベース構造からのすべての要求URLを変換するためのアイデア:

    {コントローラ}/{アクション}/{ID}パス= parentlevel1/parent2/parent3/....

90% - 両方の変種の同じコードを用意することができました。 このソリューションは、異なるコントローラを使用しているときにも役立ちます。現在のページ(ページデータ:タイプ別)で確定できるものを修正してください。

+0

もう1つのアプローチがここで説明されています:http://stackoverflow.com/questions/379558/mvc-net-routing#379823 – Nocher