MvcSiteMapProvider错误与分页

时间:2016-07-29 13:51:12

标签: asp.net-mvc routes mvcsitemapprovider

它继续ASP.NET MVC incorect generation url when using pagination,但我找到了解决方法。使用@ Html.MvcSiteMap()时如何解决这个问题.SiteMapPath()我无法理解。

在操作ShowForum或ShowTopic时以及当我使用分页时某些论坛或主题的问题。在@Html.MvcSiteMap()。SiteMapPath()中,我在父页面上获取了具有页面数量的URL

更新

对于路线配置我正在使用路线属性

    [HttpGet]
    [Route("{forumName}", Name = "showForum", Order = 6)]
    [Route("{forumName}/Page/{page}", Order = 5)]
    [OutputCache(Duration = 30, VaryByParam = "forumName;page", Location = OutputCacheLocation.ServerAndClient)]
    public async Task<ActionResult> ShowForum(string forumName, int page = 1)

    [HttpGet]
    [RefreshDetectFilter]
    [Block(VisibleBlock = false)]
    [Route("{forum}/{topicName}", Name = "showTopic", Order = 8)]
    [Route("{forum}/{topicName}/Page/{page}", Order = 7)]
    [OutputCache(Duration = 30, VaryByParam = "topicName;page", Location = OutputCacheLocation.ServerAndClient)]
    public async Task<ActionResult> ShowTopic(string forum, string topicName, int page = 1)

我的ForumDynamicNodeProvider

    public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
    {
        var rootTitle = ManagerLocalization.Get("Forums", "FORUMS");
        var pageParameter = new List<string> { "page" };
        var url = "~/Forums";
        var attr = new Dictionary<string, object> { { "Controller", "Forums" } };

        var nodes = new List<DynamicNode>
                        {
                            new DynamicNode
                                {
                                    Key = "forum_home",
                                    Title = rootTitle,
                                    Url = url,
                                    Attributes = attr
                                }
                        };

        var forums = this._forumsService.GetAllForumsForMap();
        var topics = this._forumsService.GetAllTopicsForMap();

        foreach (var forum in forums)
        {
            var forumRouteValue = new Dictionary<string, object> { { "forumName", forum.NameTranslit } };

            nodes.Add(new DynamicNode
            {
                ParentKey = forum.ForumId != -1 ? $"forum_{forum.ForumId}" : "forum_home",

                Key = $"forum_{forum.Id}",
                Title = forum.Name,
                PreservedRouteParameters = pageParameter,
                Controller = "Forums",
                Action = "ShowForum",
                RouteValues = forumRouteValue,

            });

            var forumTopics = topics.Where(item => item.ForumId == forum.Id);

            foreach (var topic in forumTopics)
            {
                var topicRouteValue = new Dictionary<string, object> { { "forum", forum.NameTranslit }, { "topicName", topic.TitleTranslite } };

                nodes.Add(new DynamicNode
                {
                    ParentKey = $"forum_{forum.Id}",
                    Key = $"topic_{topic.Id}",
                    Title = topic.Title,
                    PreservedRouteParameters = pageParameter,
                    Controller = "Forums",
                    Action = "ShowTopic",
                    RouteValues = topicRouteValue,
                });
            }
        }

        return nodes;
    }

2 个答案:

答案 0 :(得分:0)

问题是您在同一节点祖先的两个不同位置使用相同的路径键名{page}并与PreservedRouteParameters结合使用。 PreservedRouteParameters当前请求中获取其数据。因此,重要的是路由密钥在同一节点祖先的每个请求中具有相同的含义。要使它与PreservedRouteParamters一起正常工作,您需要做三件事:

  1. 为每个单独的页面参数使用不同的路由键(例如,{forumPage}{page})。
  2. 确保将祖先页面参数传递给其后代的请求,因此在构建祖先节点的URL时,该值在当前请求中。最简单的方法是使用所有祖先({forumName}/Page/{forumPage}/{topicName}/Page/{page})的页面信息构建URL。
  3. 节点之间具有相同含义的任何路由键应保持不变(两个路由中都为{forumName})。
  4. 然后,您需要在构建子节点的URL时添加参数。您必须在您的应用程序中手动构建URL,因为除非您这样做,否则请求将不会包含所有参数。

    @Html.ActionLink("TheTopicName", "ShowTopic", "Forums", 
        new { forumName = 1, forumPage = 2, topicName = "foo", page = 1 }, null)
    
      

    必须提供子节点请求中的所有数据的原因是因为祖先节点需要它来构建其URL。它从请求中提取此信息,因此它必须存在于其运行请求中。 MvcSiteMapProvider无法知道祖先节点的当前页码是什么,除非在请求中通过菜单 之外的URL提供。

    有关类似配置和解决方案,请参阅How to Make MvcSiteMapProvider Remember a User's Position代码下载中的MvcSiteMapProvider-Forcing-A-Match-2-Levels项目。在这种情况下,它使用productId而不是forumPage作为后代节点上保留的参数,以便您可以导航回到父产品。

      

    请注意,您可以为整个论坛使用类似的配置(使用PreservedRouteParametersSiteMapTitleAttribute),而不是使用动态节点提供程序。但是,在这种情况下,我会建议您disable the /sitemap.xml endpointroll your own

答案 1 :(得分:0)

我发现了这个问题,感谢 NightOwl888 。我不是第一次明白应该做什么。

首先,我删除了 ForumDynamicNodeProvider

中的初始化 PreservedRouteParameters

其次我加入了行动

        if (forumPage > 1)
        {
            var node = SiteMaps.Current.FindSiteMapNodeFromKey(forumName);

            if (node != null)
            {
                node.RouteValues["forumPage"] = forumPage;
            }
        }

我还需要在ForumDynamicNodeProvider中更改生成树,因为SiteMaps.Current在异步中不起作用