¿Es posible ocultar un elemento de menú según el rol del usuario en la aplicación MVC (lista de menú html)?

Ya me respondieron esta pregunta para la aplicación de formularios web, pero ¿puedo ocultar mi elemento del menú Administración con este código? ¿Es posible con el enlace del mapa del sitio o de lo contrario?

mi menú en: Layout.cshtml

    <ul id="navlist">
        <li class="first"> <a href="@Url.Content("~")" id="current">Home</a> </li>

        <li>
            <a href="#">User</a>
            <ul class="second">
                <li> <a href="@Url.Content("~/Service/")">> Services</a></li>
            </ul>
        </li>

        <li> 
            <a href="#">Administration</a>
            <ul class="second">
                <li><a href="@Url.Content("~/ServiceManager")">> Services</a></li>
            </ul>
        </li>

        <li>@Html.Partial("_LogOnPartial") </li>
    </ul>

preguntado el 31 de julio de 12 a las 14:07

3 Respuestas

La idoneidad de usar una declaración if simple, como se describe en Alternative, depende de:

-cuántos roles tiene (en el sentido de que puede desear evitar múltiples consultas a la base de datos, evitando múltiples

if(User.IsInRole("whatever"))

-si está utilizando un rol personalizado y un proveedor de membresía, en cuyo caso puede evitar usar User.IsInRole todos juntos, ya que abrirá una nueva conexión a la base de datos cada vez.

Brij Mohan Dammani describe una solución que tiene algunas características agradables, pero para mi gusto pone demasiada lógica en la vista. También prefiero objetos fuertemente tipados cuando sea posible en lenguajes orientados a objetos.

basado en el código descrito por Brij Dammani, ahora uso un modelo:

namespace Whatever
{
  public class RoleMenuItem: MenuItem
  {
    public RoleMenuItem(){}
    public RoleMenuItem(string linkText, string actionName, string controllerName, string roleNames)
    {
        LinkText = linkText;
        ActionName = actionName;
        ControllerName = controllerName;
        RoleNames = roleNames;
    }
    public string RoleNames { set { Roles = value.Split(new String[] { "," }, StringSplitOptions.RemoveEmptyEntries); } }
    internal string[] Roles;
  }
  public class MenuItem
  {
    public string LinkText { get; set; }
    public string ActionName { get; set; }
    public string ControllerName { get; set; }
  }
  public class RoleMenu : System.Collections.Generic.IEnumerable<MenuItem>
  {
    private readonly List<RoleMenuItem> _roleMenuItems = new List<RoleMenuItem>();
    private readonly string[] _userRoleNames;
    public readonly bool _isAuthenticated;
    public RoleMenu()
    {
        if (_isAuthenticated = WebSecurity.User.Identity.IsAuthenticated)
        {
            _userRoleNames = Roles.GetRolesForUser();
        }
    }
    public RoleMenu(IDataContext context) 
    {
        if (_isAuthenticated = WebSecurity.User.Identity.IsAuthenticated)
        {
            string userName = HttpContext.Current.User.Identity.Name;
            User usr = context.Users.FirstOrDefault(Usr => Usr.UserName == userName) ;
            _userRoleNames = (usr==null)? new string[0]: usr.Roles.Select(r => r.RoleName).ToArray(); 

        }
    }
    public RoleMenu Add(RoleMenuItem menuItem)
    {
        string[] menuRoles = menuItem.Roles;
        if (
                menuRoles.Contains("All" ) ||
                (!_isAuthenticated && menuRoles.Contains("Anonymous")) ||
                (_isAuthenticated && (menuRoles.Contains("Authenticated") || menuRoles.Any(mr=>_userRoleNames.Contains(mr))))
            )
        {
            _roleMenuItems.Add(menuItem);
        }
        return this;
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
    public System.Collections.Generic.IEnumerator<MenuItem> GetEnumerator()
    {
        return _roleMenuItems.GetEnumerator();
    } 
    public IEnumerable<MenuItem> ItemsForRole(string roleName)
    {
        return _roleMenuItems.Where(r => r.Roles.Contains(roleName));
    }
}

luego en el constructor para cada controlador (que está configurado para inyección de dependencia)

ViewBag.Menu = new RoleMenu(_db);

y en la vista _Layout

@using WhateverNamespace
<nav>
    <ul id="menu">
    @{
       RoleMenu menu = (ViewBag.Menu ?? new RoleMenu())
          .Add(new RoleMenuItem("Home", "Index", "Home","Anonymous"))
          .Add(new RoleMenuItem("Home", "Auth", "Home","Authenticated"))
          .Add(new RoleMenuItem("About", "About", "Home","All"))
          .Add(new RoleMenuItem("Administer", "Index", "Administrators","Webmaster,Administrator"))...;
       foreach (var link in menu)
       {
          <li> 
              @Html.ActionLink(link.LinkText, link.ActionName,link.ControllerName)
            ....

or

    if((var adminMenuItems=menu.ItemsFoRole("admin")).Any()) {
       <li><ul>
       foreach (var link in adminMenuItems) {
           <li> ....
       }

Respondido el 16 de Septiembre de 12 a las 03:09

Gracias por eso, no lo he probado, pero parece genial. De hecho, solo tengo dos roles, Administrador y Usuario, por lo que para mí mi condición IF es suficiente, pero su código es más completo: Alternative

Simplemente agregue esta condición IF, funciona bien. Donde "Administrador" es el Rol del usuario para el que desea mostrar este elemento de menú.

       @if(User.IsInRole("Administrator"))
           {

    <li>        
        <a href="#">Administration</a>       
        <ul class="second">       
            <li><a href="@Url.Content("~/ServiceManager")">> Services</a></li>       
        </ul>       
    </li>

        }

Respondido 31 Jul 12, 14:07

Esto solo se agregará si es un lío. La solución debe ser dinámica. - asishmohita

Puede usar esto para mostrar u ocultar según el rol del usuario:

 @using Microsoft.AspNet.Identity
    @using Microsoft.AspNet.Identity.Owin;


    @if (Request.IsAuthenticated)
    {
        var userManager = Request.GetOwinContext().GetUserManager<IdentitySample.Models.ApplicationUserManager>();
        var userRoles = userManager.GetRoles(User.Identity.GetUserId());
        var role = userRoles[0]; 

   if (role == "Admin")
        {
           <p>Hello Admin!</p>

        }


   }`

Respondido 31 ago 17, 15:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.