MvcSiteMapProvider ошибка с разбиением на страницы
При использовании нумерации страниц URL-адрес генерации неправильного ASP.NET MVC продолжается, но я обнаружил, как это исправить. Как это исправить при использовании @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)
Мой форум DynamicNodeProvider
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 ответа
Я нашел, как это исправить, спасибо NightOwl888. Я не первый раз понял, что надо делать.
Сначала я удалил инициализацию PreservedRouteParameters в ForumDynamicNodeProvider
Второе я добавил в действие
if (forumPage > 1)
{
var node = SiteMaps.Current.FindSiteMapNodeFromKey(forumName);
if (node != null)
{
node.RouteValues["forumPage"] = forumPage;
}
}
Также мне нужно изменить дерево генерации в ForumDynamicNodeProvider, потому что SiteMaps.Current не работает в асинхронном режиме.
Проблема в том, что вы используете одно и то же имя ключа маршрута {page}
в двух разных местах в одном и том же узле родословной в сочетании с PreservedRouteParameters
, PreservedRouteParameters
получает свои данные из текущего запроса. Поэтому важно, чтобы ключ маршрута имел одинаковое значение в каждом запросе в одной и той же родословной узла. Чтобы он правильно работал с PreservedRouteParamters
Вам нужно сделать три вещи:
- Используйте разные ключи маршрута для каждого отдельного параметра страницы (например,
{forumPage}
а также{page}
). - Убедитесь, что параметр страницы-предка передан в запрос его потомков, поэтому при построении URL-адреса для узла-предка значение находится в текущем запросе. Самый простой способ - создать URL с информацией о страницах всех предков (
{forumName}/Page/{forumPage}/{topicName}/Page/{page}
). - Любые ключи маршрута, имеющие одинаковое значение между узлами, должны оставаться одинаковыми (
{forumName}
в обоих направлениях).
Затем вам нужно добавить параметры при построении URL дочернего узла. Вы должны создать URL-адрес вручную в своем приложении, потому что запрос не будет иметь все параметры, если вы не сделаете это.
@Html.ActionLink("TheTopicName", "ShowTopic", "Forums",
new { forumName = 1, forumPage = 2, topicName = "foo", page = 1 }, null)
Причина, по которой вы должны предоставить все данные в запросе дочернего узла, заключается в том, что узлу-предшественнику он нужен для создания своего URL. Он извлекает эту информацию из запроса, поэтому он должен присутствовать в запросе, чтобы он функционировал.
MvcSiteMapProvider
не может знать, какой номер текущей страницы у узла-предка, если он не указан в запросе с помощью URL-адреса, созданного вне вашего меню.
Увидеть MvcSiteMapProvider-Forcing-A-Match-2-Levels
проект в загрузке кода для Как заставить MvcSiteMapProvider запомнить позицию пользователя для аналогичной конфигурации и решения. В этом случае он использует productId
вместо forumPage
в качестве параметра, который сохраняется на узлах-потомках, чтобы вы могли вернуться к родительскому продукту.
Обратите внимание, что вы можете использовать аналогичную конфигурацию (с
PreservedRouteParameters
а такжеSiteMapTitleAttribute
) для всего вашего форума, а не с использованием провайдера динамических узлов. Однако в этом случае я бы предложил отключить/sitemap.xml
конечной точки и бросить свой собственный.