MVCSiteMapProvider хлебные крошки неверный идентификатор родительского узла

У меня есть эта карта сайта:

<mvcSiteMapNode title="Projects" controller="Projects" action="Index" key="Home" visibility="!*">
<mvcSiteMapNode title="Projects" controller="Projects" action="Index">
  <mvcSiteMapNode title="Project" controller="Projects" action="Details" preservedRouteParameters="id">
    <mvcSiteMapNode title="Session" controller="Sessions" action="Details" preservedRouteParameters="id">
      <mvcSiteMapNode title="Edit Session" controller="Sessions" action="Edit" preservedRouteParameters="id"/>
    </mvcSiteMapNode>
  </mvcSiteMapNode>
</mvcSiteMapNode>
<mvcSiteMapNode title="My Account" controller="Account" action="ChangePassword" />
<mvcSiteMapNode title="Admin" controller="Admin" action="Index" >
  <mvcSiteMapNode title="Create User" controller="Admin" action="AddUser" />
  <mvcSiteMapNode title="Manage Users" controller="Admin" action="Users" />
</mvcSiteMapNode>

When I go to Session Details page, the breadcrumbs display:

Projects > Project > Session

однако ссылка на проект, которая ведет на страницу сведений о проекте, использует тот же идентификатор, что и сеанс, а не проект, из которого он был получен.

Я попытался добавить inheritedRouteParameters="id" на страницу сведений о сеансе, но ничего не изменилось.

Изменить: я добавил различные сохраненные параметры маршрута, но теперь «Проект» ссылается на / Projects / Details без привязанного идентификатора.


person Shawn    schedule 21.02.2014    source источник


Ответы (1)


savedRouteParameters всегда копирует значение из текущего запроса, если имя ключа совпадает, он не делает никаких предположений о том, что такое «id». Следовательно, если вы используете «id» в параметрах savedRouteParameters на 2 узлах, которые отображаются одновременно, вам необходимо убедиться, что они имеют одинаковое значение.

Один из способов обойти это - использовать разные ключевые имена для каждого случая (например, «projectId» и «sessionId»). Затем вы можете сохранить оба на дочернем узле, чтобы он «запомнил», какому родителю он принадлежит.

<mvcSiteMapNode title="Project" controller="Projects" action="Details" preservedRouteParameters="projectId">
    <mvcSiteMapNode title="Session" controller="Sessions" action="Details" preservedRouteParameters="projectId,sessionId">

Вам может потребоваться изменить маршруты, чтобы сделать URL-адреса приемлемыми для ваших требований, но для того, чтобы это работало, родительский идентификатор должен быть частью маршрута (и обычно URL-адреса) дочернего узла. Вот пример, который соответствует указанной выше конфигурации узла.

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "SessionRoute", 
            url: "Project/{projectId}/{sessionId}", 
            defaults: new { controller = "Sessions", action = "Details" });

        routes.MapRoute(
            name: "ProjectRoute", 
            url: "Project/{projectId}", 
            defaults: new { controller = "Projects", action = "Details" });

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

Взгляните на проект MvcSiteMapProvider-Forcing-A-Match-2-Levels в этой демонстрации, чтобы узнать, как именно это можно сделать. Обратите внимание, что добавление маршрутов не является обязательным - вы всегда можете использовать маршрут по умолчанию, если не возражаете против параметров строки запроса в URL-адресе.

Если вам это не подходит, вы можете комбинировать использование savedRouteParmeters для одного параметра узла с явной установкой другого параметра.

<mvcSiteMapNode title="Project" controller="Projects" action="Details" preservedRouteParameters="projectId">
    <mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="1" preservedRouteParameters="projectId">
    <mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="2" preservedRouteParameters="projectId">
    <mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="3" preservedRouteParameters="projectId">

Или вы можете создать узел для каждой комбинации идентификаторов, которые у вас есть.

<mvcSiteMapNode title="Project" controller="Projects" action="Details" id="1">
    <mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="1">
    <mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="2">
    <mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="3">
</mvcSiteMapNode>
<mvcSiteMapNode title="Project" controller="Projects" action="Details" id="2">
    <mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="4">
    <mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="5">
    <mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="6">
</mvcSiteMapNode>

Для этих двух последних вариантов обычно лучше использовать DynamicNodeProvider для заполнения динамических данных, а не для их разметки в XML.

Эти методы создают более чистые URL-адреса, но при этом используют больше оперативной памяти. Как правило, для административных страниц лучше использовать слегка неаккуратные URL-адреса (savedRouteParmaters) и сохранять с использованием динамических узлов (и ОЗУ) для страниц, требующих индексации поисковой системой.

inheritedRouteParameters предназначено только для наследования значений от родительского узла в конфигурации XML и не действует на уровне запроса.

Кстати - вы должны убедиться, что у вас есть уникальная комбинация значений маршрута на каждом узле. В вашем примере первые 2 узла имеют точно такие же значения маршрута, что означает, что второй никогда не будет сопоставлен, потому что первое совпадение всегда побеждает.

person NightOwl888    schedule 21.02.2014
comment
Не работает ли у меня решение savedRouteParameters, потому что я использую маршрутизацию по умолчанию и разные контроллеры? - person Shawn; 24.02.2014
comment
На самом деле это не имеет ничего общего с маршрутизацией - это потому, что вы используете одно и то же имя для параметра в 2 разных узлах, которые потенциально могут отображаться одновременно. savedRouteParameters не запоминает идентификатор между запросами, он только копирует его из текущего. Если у вас есть узел-предок, который использует тот же идентификатор для другой цели, он будет использовать неправильный идентификатор при просмотре дочернего узла. - person NightOwl888; 25.02.2014
comment
Прочтите этот пост, чтобы лучше понять, как работает savedRouteParameters. shiningtreasures.com/ post / 2013/09/02 / - person NightOwl888; 25.02.2014
comment
Я создал новый проект под названием MvcSiteMapProvider-Forcing-A-Match-2-Levels, чтобы продемонстрировать, как это сделать. github.com/NightOwl888/ - person NightOwl888; 25.02.2014
comment
Я пробовал первый пример, и он не работает для меня, если не preservedRouteParameters="id". Он не принимает другие имена для id. - person user1012732; 11.02.2016
comment
Как я указал в своем ответе, вам, конечно, потребуется добавить дополнительные маршруты в свою таблицу маршрутов, если вы хотите использовать другое имя параметра. Я добавил к своему ответу пример. - person NightOwl888; 11.02.2016