带有分页的 MvcSiteMapProvider 错误
MvcSiteMapProvider bug with 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;
}
问题是您在同一节点祖先的两个不同位置使用相同的路由键名称 {page}
并结合 PreservedRouteParameters
。 PreservedRouteParameters
从 current 请求中获取数据。因此,重要的是路由键在同一节点祖先的每个请求中具有相同的含义。要使其与 PreservedRouteParamters
一起正常工作,您需要做三件事:
- 为每个单独的页面参数使用不同的路由键(例如,
{forumPage}
和 {page}
)。
- 确保将祖先页面参数传递给其后代的请求,因此在将 URL 构建到祖先节点时,该值在当前请求中。最简单的方法就是用所有祖先(
{forumName}/Page/{forumPage}/{topicName}/Page/{page}
)的页面信息构建URL。
- 任何在节点之间具有相同含义的路由键应该保持相同(
{forumName}
在两个路由中)。
那么需要在构建子节点的URL时添加参数。您必须在您的应用程序中手动构建URL,因为除非您这样做,否则请求不会包含所有参数。
@Html.ActionLink("TheTopicName", "ShowTopic", "Forums",
new { forumName = 1, forumPage = 2, topicName = "foo", page = 1 }, null)
The reason you must supply all of the data in the child node request is because the ancestor node needs it to build its URL. It pulls this information from the request, so it must be present in the request for it to function. MvcSiteMapProvider
has no way of knowing what the current page number of the ancestor node is unless it is provided in the request by a URL that is built outside of your menu.
请参阅 How to Make MvcSiteMapProvider Remember a User's Position 代码下载中的 MvcSiteMapProvider-Forcing-A-Match-2-Levels
项目,了解类似的配置和解决方案。在这种情况下,它使用 productId
而不是 forumPage
作为保留在后代节点上的参数,因此您可以导航回父产品。
Note that you could use a similar configuration (with PreservedRouteParameters
and SiteMapTitleAttribute
) for your entire forum rather than using a dynamic node provider. However, in that case I would suggest you disable the /sitemap.xml
endpoint and roll your own.
我找到了这个修复方法,谢谢 NightOwl888。我不是第一次明白该怎么办了。
首先我在ForumDynamicNodeProvider
中删除了初始化PreservedRouteParameters
第二个我在行动中添加
if (forumPage > 1)
{
var node = SiteMaps.Current.FindSiteMapNodeFromKey(forumName);
if (node != null)
{
node.RouteValues["forumPage"] = forumPage;
}
}
我还需要更改 ForumDynamicNodeProvider 中的生成树,因为 SiteMaps.Current 在异步中不起作用
它继续
问题在于,在执行 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;
}
问题是您在同一节点祖先的两个不同位置使用相同的路由键名称 {page}
并结合 PreservedRouteParameters
。 PreservedRouteParameters
从 current 请求中获取数据。因此,重要的是路由键在同一节点祖先的每个请求中具有相同的含义。要使其与 PreservedRouteParamters
一起正常工作,您需要做三件事:
- 为每个单独的页面参数使用不同的路由键(例如,
{forumPage}
和{page}
)。 - 确保将祖先页面参数传递给其后代的请求,因此在将 URL 构建到祖先节点时,该值在当前请求中。最简单的方法就是用所有祖先(
{forumName}/Page/{forumPage}/{topicName}/Page/{page}
)的页面信息构建URL。 - 任何在节点之间具有相同含义的路由键应该保持相同(
{forumName}
在两个路由中)。
那么需要在构建子节点的URL时添加参数。您必须在您的应用程序中手动构建URL,因为除非您这样做,否则请求不会包含所有参数。
@Html.ActionLink("TheTopicName", "ShowTopic", "Forums",
new { forumName = 1, forumPage = 2, topicName = "foo", page = 1 }, null)
The reason you must supply all of the data in the child node request is because the ancestor node needs it to build its URL. It pulls this information from the request, so it must be present in the request for it to function.
MvcSiteMapProvider
has no way of knowing what the current page number of the ancestor node is unless it is provided in the request by a URL that is built outside of your menu.
请参阅 How to Make MvcSiteMapProvider Remember a User's Position 代码下载中的 MvcSiteMapProvider-Forcing-A-Match-2-Levels
项目,了解类似的配置和解决方案。在这种情况下,它使用 productId
而不是 forumPage
作为保留在后代节点上的参数,因此您可以导航回父产品。
Note that you could use a similar configuration (with
PreservedRouteParameters
andSiteMapTitleAttribute
) for your entire forum rather than using a dynamic node provider. However, in that case I would suggest you disable the/sitemap.xml
endpoint and roll your own.
我找到了这个修复方法,谢谢 NightOwl888。我不是第一次明白该怎么办了。
首先我在ForumDynamicNodeProvider
中删除了初始化PreservedRouteParameters第二个我在行动中添加
if (forumPage > 1)
{
var node = SiteMaps.Current.FindSiteMapNodeFromKey(forumName);
if (node != null)
{
node.RouteValues["forumPage"] = forumPage;
}
}
我还需要更改 ForumDynamicNodeProvider 中的生成树,因为 SiteMaps.Current 在异步中不起作用