Несколько путей к одному и тому же представлению 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>