【问题标题】:MvcSiteMapProvider bug with pagination带有分页的 MvcSiteMapProvider 错误
【发布时间】:2016-07-29 13:51:11
【问题描述】:

它继续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)

我的论坛动态节点提供者

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

【问题讨论】:

  • 请发布您的节点配置。您还应该在此处发布您的路由配置(而不是链接到另一个问题),因为它与分页有关。目前尚不清楚您的另一个问题的“解决方案”是什么 - 看来您只是将分页从路线中移除。
  • 好的。我添加了路由配置和 ForumDynamicNodeProvider

标签: asp.net-mvc routes mvcsitemapprovider


【解决方案1】:

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

  1. 为每个单独的页面参数使用不同的路由键(例如,{forumPage}{page})。
  2. 确保将祖先页面参数传递给其后代的请求,因此在构建祖先节点的 URL 时,该值在当前请求中。最简单的方法是使用所有祖先的页面信息({forumName}/Page/{forumPage}/{topicName}/Page/{page})构建 URL。
  3. 在节点之间具有相同含义的任何路由键都应保持不变({forumName} 在两个路由中)。

然后需要在构建子节点的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

【讨论】:

  • 如果正确的话。更改路线的键。对主题的帮助,但对于子论坛并没有帮助我
  • 我已经更新了我的答案。我不确定我怎么能比这更清楚,因为我已经提供了一个工作示例 - 使用 PreservedRouteParameters 时,所有数据都需要在子节点的请求中,否则祖先 URL 不会被建造。
  • 我是怎么写的,我解决了主题链接的问题,当我使用分页时,我在论坛中遇到了@Html.MvcSiteMap().SiteMapPath() 的问题
【解决方案2】:

我找到了解决方法,感谢 NightOwl888。我不是第一次明白该怎么做。

首先我删除了 ForumDynamicNodeProvider

中的初始化 PreservedRouteParameters

第二次我在行动中添加

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

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

我还需要 ForumDynamicNodeProvider 中的更改生成树,因为 SiteMaps.Current 不能异步工作

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-29
    • 1970-01-01
    • 2019-03-06
    相关资源
    最近更新 更多