【问题标题】:Asp.net mvc 3.0 tree structure page custom routingasp.net mvc 3.0 树形结构页面自定义路由
【发布时间】:2011-06-30 06:08:24
【问题描述】:

我想将所有 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

【问题讨论】:

    标签: asp.net-mvc seo asp.net-mvc-routing url-routing


    【解决方案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;
      }
    }
    

    【讨论】:

    • 谢谢山姆,这就是我要找的。非常感谢=)
    • 嗨 Sam,BuildPath 函数有什么作用?
    • 刚刚添加了BuildPath功能及说明。
    【解决方案2】:

    之前提出的解决方案仅适用于少量页面。 因为根据代码:

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

    还有另外两种方法可以解决这个问题:

    • 您可以创建一个派生自 RouteBase 的类并实现您需要的属性和方法:将 url 拆分为段,确定当前页面填充 RouteValueDictionary 与 pageid、路径、父级等

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

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

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

    【讨论】:

    猜你喜欢
    • 2010-10-07
    • 2011-04-02
    • 2020-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    • 2015-06-22
    相关资源
    最近更新 更多