Почему карта сайта MVC скрывает пункты меню, где существуют действия на контроллере? - PullRequest
2 голосов
/ 26 мая 2011

Я использую карту сайта 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 ]

4 голосов
/ 27 мая 2011

Я выяснил проблему. Метод InRole () пользователя HttpContext используется в модуле MvcSiteMapProvider.DefaultAclModule в коде библиотеки. Я использую проверку подлинности с помощью форм, что означает, что InRole никогда не будет работать, так как свойство role в пользовательском контексте не установлено (оно не знает, как применяются роли).

Я мог бы написать свой собственный поставщик 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);
                }
            }
        }
1 голос
/ 09 октября 2013

@ яффо, твой подход помог мне !! Благодарю. Вот как я это реализовал .. может быть, это может помочь и другим!

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>

указание реализованного контроллера в VisibilityProvider должно служить цели.

...