Asp.net mvc Asp.net mvc 3.0树结构页面自定义路由

Asp.net mvc Asp.net mvc 3.0树结构页面自定义路由,asp.net-mvc,seo,asp.net-mvc-routing,url-routing,Asp.net Mvc,Seo,Asp.net Mvc Routing,Url Routing,我想将所有CMS页面url映射到单个控制器(PageController)和操作(详细信息) 如何创建自定义路由来映射所有这些URL /teacher /teacher/kindergarten /teacher/kindergarten/1 /teacher/primary /teacher/primary/english /teacher/primary/language /teacher/primary/language/chinese /teacher/primary/math /tea

我想将所有CMS页面url映射到单个控制器(PageController)和操作(详细信息)

如何创建自定义路由来映射所有这些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

如果数据库中有这些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链接

以下是生成每个页面的完整路径的BuildPath函数:

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;
  }
}

以前提出的解决方案仅适用于少量页面。 因为根据守则:

应用程序生成并注册每个站点页面的路由。结果,我们至少有相同数量的路由作为网页在我们的网站。正如您可能知道的,RouteModule必须逐个路由检查每个路由,以找到第一个正确的路由,并执行正确的处理程序、控制器、操作、视图

解决这个问题还有两种方法:

  • 您可以创建一个从RouteBase派生的类,并实现所需的属性和方法:将url拆分为段,确定当前页面使用pageid、path、parents等填充RouteValueDictionary

  • 您可以使用自定义URLEwriteModule。将所有请求url从树状结构转换为mvc默认路由的想法:

    {controller}/{action}/{id}?path=parentlevel1/parent2/parent3/

90%-可为两种变体编制相同的代码。
当您有不同的控制器时,该解决方案也很有用,正确的控制器我们可以通过当前页面确定(按页面数据:类型)

谢谢Sam,这就是我要找的。非常感谢=)嗨,Sam,BuildPath函数将做什么?刚刚添加了BuildPath函数和解释。这里介绍了另一种方法: