Почему карта сайта MVC скрывает пункты меню, где существуют действия на контроллере?
Я использую карту сайта MVC для MVC3, но у меня проблемы с ней. Рассмотрим следующий файл карты сайта:
<?xml version="1.0" encoding="utf-8" ?>
<mvcSiteMap xmlns="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-3.0" enableLocalization="true">
<mvcSiteMapNode title="Home" controller="Home" action="Index" changeFrequency="Always" updatePriority="Normal" Description="Test HOME">
<mvcSiteMapNode title="Today" controller="Dashboard" action="Today" />
<mvcSiteMapNode title="Today1" controller="Dashboard" action="Today1" />
<mvcSiteMapNode title="Today2" controller="Dashboard" action="Today2" />
<mvcSiteMapNode title="Today3" controller="Dashboard" action="Today3" />
<mvcSiteMapNode title="Today4" controller="Dashboard" action="Today4" />
</mvcSiteMapNode>
</mvcSiteMap>
Когда я загружаю свою веб-страницу, я получаю только следующие опции:
Сегодня1, Сегодня2, Сегодня3, Сегодня4
Но сегодня не отображается. Это действие на контроллере, тогда как другие действия не существуют. Почему он скрывает элемент, который фактически существует на контроллере? Я снял авторизацию на контроллере, чтобы исключить, что он имеет какое-либо отношение к авторизации, но все же эффект.
Это конфиг карты сайта (установлен в web.config):
<siteMap defaultProvider="MvcSiteMapProvider" enabled="true">
<providers>
<clear />
<add name="MvcSiteMapProvider"
type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider"
siteMapFile="~/Mvc.Sitemap"
securityTrimmingEnabled="true"
cacheDuration="5"
enableLocalization="true"
scanAssembliesForSiteMapNodes="false"
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>
</system.web>
2 ответа
Я выясняю проблему. Метод InRole() пользователя HttpContext используется в модуле MvcSiteMapProvider.DefaultAclModule в коде библиотеки. Я использую проверку подлинности с помощью форм, что означает, что InRole никогда не будет работать, так как свойство Роли в пользовательском контексте не установлено (оно не знает, как применяются роли).
Я мог бы либо написать свой собственный поставщик aclmodule, который проверяет билет аутентификации для ролей, хранящихся в билете, либо, альтернативно, для каждого события запроса аутентификации в global.asax, устанавливать контекст с установленными ролями. В итоге я выбрал последнее:
например
if (HttpContext.Current.User != null)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
if (HttpContext.Current.User.Identity is FormsIdentity)
{
FormsIdentity formsId = (FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = formsId.Ticket;
// need to do this so MVC sitemap IsInRole works inside default acl module: MvcSiteMapProvider.DefaultAclModule
var authData = new AuthenticationModel(ticket.UserData);
var roles = new List<string>(authData.EffectiveRoles).ToArray();
HttpContext.Current.User = new GenericPrincipal(formsId, roles);
}
}
}
@jaffa, твой подход помог мне!! Благодарю. Вот как я это реализовал.. может быть, это может помочь и другим!
public class MenuVisibilityController : Controller, ISiteMapNodeVisibilityProvider
{
public bool IsVisible(SiteMapNode Node, HttpContext context, IDictionary<string, object> sourceMetadata)
{
return context.User.Identity.IsAuthenticated;
}
}
Реализовал провайдера видимости для карты сайта MVC, а затем использовал его для видимости определенного узла, как показано ниже:
<mvcSiteMapNode title="Test Menu" controller="Account" action="Index" visibilityProvider="MyProject.Controllers.MenuVisibilityController, MyProject">
<mvcSiteMapNode title="Test Item 1" controller="Account" action="GetItems" />
</mvcSiteMapNode>
указание реализованного контроллера в Visibility Provider должно служить цели.