Несколько путей к одному и тому же представлению Razor - ASP.NET MVC с использованием SiteMap Provider

У меня Asp.NET MVC SiteMap Provider версии 4.0.

Я написал небольшой тестовый проект, который имеет несколько тестовых видов Razor. Вот MvcSite XML-файл, который имеет определенные пути:

 <mvcSiteMapNode title="Home - default" controller="Home" action="Index">
    <mvcSiteMapNode title="Middle - default" controller="Home" action="Middle">
      <mvcSiteMapNode title="Edit - default" controller="Home" action="Edit" key="keyForEdit">
      </mvcSiteMapNode>
    <mvcSiteMapNode title="Over - another path" controller="Home" action="Over">
      <mvcSiteMapNode title="Edit through over" controller="Home" action="Edit" canonicalKey="keyForEdit">
      </mvcSiteMapNode>
    </mvcSiteMapNode>
    </mvcSiteMapNode>
  </mvcSiteMapNode>
</mvcSiteMap>

Идея состоит в том, чтобы получить представление "Редактировать" из разных мест приложения. Я могу пройти через "Середину" или через "За" Razor view. Моя цель состоит в том, чтобы иметь разные дисплеи bredcrumb для этих разных путей к представлению "Изменить". Вот мастер-макет, на котором построен сайт:

    @{
        Layout = null;
    }

    <!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>This is layout</title>
    @Html.MvcSiteMap().CanonicalTag()
</head>
<body>
    <div>Hi from Layout!</div>
    <div>@Html.MvcSiteMap().SiteMapPath()</div>
    <div>
        @RenderBody()
    </div>
</body>
</html>

Тем не менее, каждый раз, когда я получаю представление "Редактировать", у меня есть заголовок "Редактировать - по умолчанию" внутри крошки. Почему это? Большое спасибо за уделенное время.

1 ответ

Решение

Причина этого в том, что у вас есть 2 разных узла с одинаковой сигнатурой маршрута. Когда это происходит, первое совпадение всегда выигрывает при определении текущего узла (узла для текущего запроса).

Для вашего примера оба URL имеют маршрут, который выглядит следующим образом.

|-----------------------------------|-----------------------------------|
|         Current Request           |          SiteMap Node             |
|-----------------------------------|-----------------------------------|
|      Key       |      Value       |      Key       |      Value       |
|-----------------------------------|-----------------------------------|
| controller     | Home             | controller     | Home             |
| action         | Edit             | action         | Edit             |
|-----------------------------------|-----------------------------------|

Проблема в том, что не существует уникального способа добраться до второго узла, поэтому он никогда не будет совпадать. Кроме того, URL (и маршрут) будут одинаковыми в обоих случаях.

Чтобы это работало правильно, подпись маршрута должна быть уникальной для каждого узла, даже если они представляют одно и то же местоположение. Самый простой способ добиться этого - добавить дополнительный параметр для создания другой подписи маршрута и другого URL-адреса для одного из случаев.

<mvcSiteMapNode title="Home - default" controller="Home" action="Index">
    <mvcSiteMapNode title="Middle - default" controller="Home" action="Middle">
        <mvcSiteMapNode title="Edit - default" controller="Home" action="Edit" key="keyForEdit"/>
    </mvcSiteMapNode>
    <mvcSiteMapNode title="Over - another path" controller="Home" action="Over">
        <mvcSiteMapNode title="Edit through over" controller="Home" action="Edit" category="path2" canonicalKey="keyForEdit"/>
    </mvcSiteMapNode>
</mvcSiteMapNode>

При использовании маршрута по умолчанию первая страница редактирования сгенерирует URL /Home/Edit а второй сгенерирует URL /Home/Edit?category=path2, Это дает MvcSiteMapProvider достаточно информации, чтобы определить разницу между двумя местоположениями, поскольку они теперь уникальны. Вот как выглядит второй.

|-----------------------------------|-----------------------------------|
|         Current Request           |          Default Node             |
|-----------------------------------|-----------------------------------|
|      Key       |      Value       |      Key       |      Value       |
|-----------------------------------|-----------------------------------|
| controller     | Home             | controller     | Home             |
| action         | Edit             | action         | Edit             |
| category       | path2            |                                   |   
|-----------------------------------|-----------------------------------|


|-----------------------------------|-----------------------------------|
|         Current Request           |        Another Path Node          |
|-----------------------------------|-----------------------------------|
|      Key       |      Value       |      Key       |      Value       |
|-----------------------------------|-----------------------------------|
| controller     | Home             | controller     | Home             |
| action         | Edit             | action         | Edit             |
| category       | path2            | category       | path2            |
|-----------------------------------|-----------------------------------|

Поэтому, когда текущий маршрут запроса включает category=path2, он теперь будет соответствовать второму узлу при поиске текущего узла и не сможет найти первый из-за дополнительного параметра.

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

Взгляните на MvcSiteMapProvider - Учебное пособие по SEO для примера и загружаемого демонстрационного проекта. Кроме того, это может помочь, если вы просмотрите, как заставить MvcSiteMapProvider запомнить позицию пользователя, если вы собираетесь использовать собственную схему URL.

Вы можете использовать URL в узлах mvc.sitemap:

<mvcSiteMapNode title="Home - default" controller="Home" action="Index">
    <mvcSiteMapNode title="Middle - default" controller="Home" action="Middle">
        <mvcSiteMapNode title="Edit - default" controller="Home" action="Edit" key="keyForEdit" url="/Home/Edit"/>
    </mvcSiteMapNode>
    <mvcSiteMapNode title="Over - another path" controller="Home" action="Over">
        <mvcSiteMapNode title="Edit through over" controller="Home" action="Edit" url="/Home/Edit/Path2" canonicalKey="keyForEdit"/>
    </mvcSiteMapNode>
</mvcSiteMapNode>
Другие вопросы по тегам