Использование нескольких MvcSiteMaps - PullRequest
8 голосов
/ 24 февраля 2012

Я недавно столкнулся с проблемой, пытаясь использовать MvcSiteMapProvider .

В моем приложении у меня есть три различных области: Landing, Application и Administration.В настоящее время я реализовал MvcSiteMapProvider, и он работает потрясающе, но сейчас я пытаюсь сделать это - использовать Html MvcSiteMap Helper и указать другого поставщика карт в зависимости от области, в которой я нахожусь.

Итак, когда я:

  • В области «Администратор» - я хочу использовать провайдера с именем «AdminSiteMapProvider».
  • В области «Приложение» - я хочу использоватьпоставщик с именем «AppSiteMapProvider».

Я пробовал следующее:

Shared -> _AppLayout.cshtml

@Html.Partial("_Menu")

Shared -> _Menu.cshtml

@{
if (HttpContext.Current != null && HttpContext.Current.Handler is System.Web.Mvc.MvcHandler)
{
    var handler = HttpContext.Current.Handler as System.Web.Mvc.MvcHandler;
    var currentArea = handler.RequestContext.RouteData.Values["area"] ?? string.Empty;
    if (!string.IsNullOrEmpty(currentArea.ToString()))
    {
        <text>@Html.MvcSiteMap("AppSiteMapProvider").Menu()</text>
    }
    else if (currentArea.ToString() == "Admin")
    {
        <text>@Html.MvcSiteMap("AdminSiteMapProvider").Menu()</text>    
    }
}    

}

Есть предложения?Я не хочу копировать / вставлять содержимое _AppLayout.cshtml в новый мастер только для одной области, я бы предпочел, чтобы он выбирал подходящего поставщика динамически.

Ответы [ 4 ]

8 голосов
/ 28 февраля 2012

Добавьте что-то вроде этого в ваш файл web.config (новый провайдер для каждой области):

<siteMap defaultProvider="AppSiteMapProvider" enabled="true">
  <providers>
    <clear />
    <add name="AppSiteMapProvider" type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider" siteMapFile="~/Mvc.Sitemap" securityTrimmingEnabled="true" cacheDuration="5" enableLocalization="true" scanAssembliesForSiteMapNodes="true" includeAssembliesForScan="" excludeAssembliesForScan="" attributesToIgnore="visibility" nodeKeyGenerator="MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvider" controllerTypeResolver="MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvider" actionMethodParameterResolver="MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvider" aclModule="MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvider" siteMapNodeUrlResolver="MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver, MvcSiteMapProvider" siteMapNodeVisibilityProvider="MvcSiteMapProvider.DefaultSiteMapNodeVisibilityProvider, MvcSiteMapProvider" siteMapProviderEventHandler="MvcSiteMapProvider.DefaultSiteMapProviderEventHandler, MvcSiteMapProvider" />
    <add name="AdminSiteMapProvider" type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider" siteMapFile="~/Areas/Admin/Mvc.Sitemap" securityTrimmingEnabled="true" cacheDuration="5" enableLocalization="true" scanAssembliesForSiteMapNodes="true" includeAssembliesForScan="" excludeAssembliesForScan="" attributesToIgnore="visibility" nodeKeyGenerator="MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvider" controllerTypeResolver="MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvider" actionMethodParameterResolver="MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvider" aclModule="MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvider" siteMapNodeUrlResolver="MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver, MvcSiteMapProvider" siteMapNodeVisibilityProvider="MvcSiteMapProvider.DefaultSiteMapNodeVisibilityProvider, MvcSiteMapProvider" siteMapProviderEventHandler="MvcSiteMapProvider.DefaultSiteMapProviderEventHandler, MvcSiteMapProvider" />
  </providers>
</siteMap>

Поместите это на свою общую главную страницу (то же самое для меню):

var currentArea = (string)ViewContext.RouteData.DataTokens["area"];
if (string.IsNullOrWhiteSpace(currentArea))
{
    <text>@Html.MvcSiteMap("AppSiteMapProvider").SiteMapTitle()</text>
}
else if (currentArea.ToString() == "Admin")
{
    <text>@Html.MvcSiteMap("AdminSiteMapProvider").SiteMapTitle()</text>
}

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

Это работает для меня.Надеюсь, это поможет.

6 голосов
/ 23 декабря 2014

Я использую версию 4, для которой указанные провайдеры, очевидно, не работают. предписанный способ иметь несколько карт сайта в v4 , откровенно напугал bejeebus из меня и был намного большим количеством работы, чем я хотел.

Согласно комментарию предложения @ NightOwl888 относительно его собственного ответа, я использовалопция именованных помощников в v4.У меня все еще есть только один файл mvc.sitemap, но у меня есть взаимоисключающие параметры видимости.

Шаг 1: добавьте этот параметр в web.config

<add key="MvcSiteMapProvider_DefaultSiteMapNodeVisibiltyProvider" value="MvcSiteMapProvider.FilteredSiteMapNodeVisibilityProvider, MvcSiteMapProvider"/>

Шаг 2: выберите именаваших различных «меню» и примените их к атрибуту visibility на каждом узле.В моем случае у меня были «Обычный» и «Админ».Опять же, все они находятся в одном файле mvc.sitemap.

<mvcSiteMapNode title="Reports" controller="Report" action="List" visibility="Regular,!*"/>
<mvcSiteMapNode title="Downloads" controller="Download" action="List" visibility="Regular,!*"/>
<mvcSiteMapNode title="Documents" controller="Document" action="List" visibility="Regular,!*"/>

<mvcSiteMapNode title="Users" controller="User" action="List" visibility="Admin,!*"/>
<mvcSiteMapNode title="Projects" controller="Project" action="List" visibility="Admin,!*"/>
<mvcSiteMapNode title="Misc" clickable="false" visibility="Admin,!*">
    <mvcSiteMapNode title="Reports" controller="Report" action="List" visibility="Admin,!*"/>
    <mvcSiteMapNode title="Downloads" controller="Download" action="List" visibility="Admin,!*"/>
    <mvcSiteMapNode title="Documents" controller="Document" action="List" visibility="Admin,!*"/>
</mvcSiteMapNode>

Вы заметите, что ссылки «Отчеты», «Загрузки» и «Документы» доступны как обычным пользователям, так и администраторам, но поскольку администратор редкоиспользует эти параметры, я хотел поместить их в подменю Misc.

Шаг 3: в вашем _Layout.cshtml выберите, какое меню вы хотите отобразить.

@if(User.IsInRole("Admin"))
{
    @Html.MvcSiteMap().Menu("BootstrapMenuHelperModel", false, new { name = "Admin" })
}
else
{
    @Html.MvcSiteMap().Menu("BootstrapMenuHelperModel", false, new { name = "Regular" })
}

Я использовал это учебник по начальной загрузке / карте сайта , если нет, думаю, вы можете просто позвонить @Html.MvcSiteMap().Menu(new { name = "MENUNAME" })

5 голосов
/ 20 августа 2013

Несколько файлов Sitemap в одном приложении объясняет, как это делается в версии 4, которая несколько отличалась от принятого ответа, который был для версии 3 и более ранних версий.

Основное отличие заключается вчто теперь несколько карт сайта настроены с помощью DI, и вам необходимо реализовать ISiteMapCacheKeyGenerator и / или ISiteMapCacheKeyToBuilderSetMapper, которые представляют собой небольшие классы, чтобы сообщить MvcSiteMapProvider, как сопоставлять входящие запросы HTTP с каждой картой сайта.

2 голосов
/ 06 июля 2012

Это то, что я в итоге сделал (основываясь на этом вопросе).это немного проще, надеюсь, это поможет.Я только что назвал своего провайдера карты сайта в честь области, или "по умолчанию".

<ul id="menu">
@{
    // gets a different sitemap for each area (or the default one)
    var _siteMap = ViewContext.RouteData.DataTokens["area"] 
                        as string ?? "Default";
    var sm = Html.MvcSiteMap(_siteMap);
    @sm.Menu(sm.Provider.RootNode, true, true, 2);
}
</ul>
...