Usando più mvcsitemaps.
-
12-11-2019 - |
Domanda
Ho recentemente colpito un blocco stradale cercando di utilizzare il mvcsitemapprovider .
Nella mia applicazione, ho tre aree distinte: atterraggio, applicazione e amministrazione.Attualmente ho implementato il MVCSITEMApprovverider e funziona incredibilmente, ma quello che sto cercando di fare ora - è utilizzare l'helper HTML MvCsitemap e specificare un fornitore di mappe diverse a seconda dell'area in cui sono.
Allora, quando sono:
- .
- Nell'area "Admin" - Voglio utilizzare il provider denominato "AdminsIteMapprovider".
- Nell'area "Applicazione" - Voglio utilizzare il provider denominato "AppSiteMapprovider".
Ho provato quanto segue:
condiviso -> _aplayout.cshtml
.@Html.Partial("_Menu")
condiviso -> _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> } }
}
Qualche suggerimento?Non voglio dover copiare / incollare il contenuto _aplayout.cshtml in un nuovo master solo per un'area, preferirei che selezionare il fornitore giusto dinamicamente.
Soluzione
Aggiungi qualcosa come questo nel tuo file web.config (un nuovo fornitore per ogni area):
<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>
.
Metti questo nella tua masterpage comune (stessa cosa per il menu):
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>
}
.
e finaly Crea un file sitemap per ogni area.
funziona per me.Spero che aiuti.
Altri suggerimenti
Sto usando la versione 4, per i quali apparentemente i fornitori denominati non funzionano. Il modo prescritto per avere più sitemaps in V4 francamente spaventato Il bejeebus da me e era molto più lavoro di quanto volessi.
Per il commento del suggerimento @ Nightwlowlowl888 sulla sua stessa risposta, ho usato l'opzione Named Helphers in V4. Ho ancora un solo file MVC.Sitemap, ma ho opzioni di visibilità reciprocamente esclusive.
Step 1: aggiungi questa impostazione su Web.config
<add key="MvcSiteMapProvider_DefaultSiteMapNodeVisibiltyProvider" value="MvcSiteMapProvider.FilteredSiteMapNodeVisibilityProvider, MvcSiteMapProvider"/>
.
Step 2: scegli i nomi dei tuoi diversi "menu" e applicarli all'attributo visibility
su ciascun nodo. Nel mio caso avevo "regolare" e "admin". Di nuovo, tutti questi sono nello stesso file 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>
.
Noterai che i report, i download e i collegamenti documenti sono disponibili per utenti regolari e utenti amministratori, ma poiché l'admin utilizza raramente queste opzioni, volevo metterli nel sottomenu Misc.
Step 3: Nel tuo _Layout.cshtml, decidi quale menu si desidera visualizzare.
@if(User.IsInRole("Admin"))
{
@Html.MvcSiteMap().Menu("BootstrapMenuHelperModel", false, new { name = "Admin" })
}
else
{
@Html.MvcSiteMap().Menu("BootstrapMenuHelperModel", false, new { name = "Regular" })
}
.
Ho usato questo Bootstrap / Sitemap Tutorial , se non sei penso che puoi chiamare @Html.MvcSiteMap().Menu(new { name = "MENUNAME" })
più sitemaps in un'unica applicazione spiega come questoè fatto in V4, che è cambiato un bel po 'dalla risposta accettata - che era per V3 e prima.
La differenza principale è che ora si configurano più sitemaps sono configurate con DI e è necessario implementare ISITEMAPCacheKeyGenerator e / o ISITemapCachekeyTobuilderseTeckapper, che sono piccole classi da dire a MVCSITEMapprovider come mappare le richieste HTTP in entrata a ciascun sito.
Questo è ciò che ho finito per fare (in base a questa domanda).È un po 'più semplice, spero che aiuti.Ho appena nominato il mio sito map del sito dopo l'area o "predefinito".
<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>
.