32

Am I able to hide certain menu items in an asp:Menu control based on role?

<asp:Menu ID="mTopMenu" runat="server" Orientation="Horizontal" />
    <Items>
        <asp:MenuItem Text="File">
            <asp:MenuItem Text="New Project" />
            <asp:MenuItem Text="Release Template" NavigateUrl="~/Release/ReleaseTemplate.aspx" />
            <asp:MenuItem Text="Release Schedule" NavigateUrl="~/Release/ReleaseSchedule.aspx" />
            <asp:MenuItem Text="Roles" NavigateUrl="~/Admin/AdminRoles.aspx" />
        </asp:MenuItem>
    </Items>
</asp:Menu>

How can I make one of these items visible to only users in the Admin role? I am using asp.net role provider.

techturtle
  • 2,519
  • 5
  • 28
  • 54
kacalapy
  • 9,806
  • 20
  • 74
  • 119

10 Answers10

28

You can remove unwanted menu items in Page_Load, like this:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Roles.IsUserInRole("Admin"))
        {
            MenuItemCollection menuItems = mTopMenu.Items;
            MenuItem adminItem = new MenuItem();
            foreach (MenuItem menuItem in menuItems)
            {
                if (menuItem.Text == "Roles")
                    adminItem = menuItem;
            }
            menuItems.Remove(adminItem);
        }
    }

I'm sure there's a neater way to find the right item to remove, but this one works. You could also add all the wanted menu items in a Page_Load method, instead of adding them in the markup.

Jon Hallin
  • 508
  • 3
  • 9
22

You can bind the menu items to a site map and use the roles attribute. You will need to enable Security Trimming in your Web.Config to do this. This is the simplest way.

Site Navigation Overview: http://msdn.microsoft.com/en-us/library/e468hxky.aspx

Security Trimming Info: http://msdn.microsoft.com/en-us/library/ms178428.aspx

SiteMap Binding Info: http://www.w3schools.com/aspnet/aspnet_navigation.asp

Good Tutorial/Overview here: http://weblogs.asp.net/jgalloway/archive/2008/01/26/asp-net-menu-and-sitemap-security-trimming-plus-a-trick-for-when-your-menu-and-security-don-t-match-up.aspx

Another option that works, but is less ideal is to use the loginview control which can display controls based on role. This might be the quickest (but least flexible/performant) option. You can find a guide here: http://weblogs.asp.net/sukumarraju/archive/2010/07/28/role-based-authorization-using-loginview-control.aspx

theChrisKent
  • 15,029
  • 3
  • 61
  • 62
14

I prefer to use the FindItem method and use the value path for locating the item. Make sure your PathSeparator property on the menu matches what you're using in FindItem parameter.

    protected void Page_Load(object sender, EventArgs e)
    {

        // remove manage user accounts menu item for non-admin users.
        if (!Page.User.IsInRole("Admin"))
        {
            MenuItem item = NavigationMenu.FindItem("Users/Manage Accounts");
            item.Parent.ChildItems.Remove(item);  
        }

    }
BMASolutions
  • 201
  • 2
  • 2
  • You should probably do the above in the Menu's DataBound event rather than in Page_Load, since the DataBound event will run every time the data's bound to the menu, which could happen after Page_Load). – Scott Mitchell Oct 03 '13 at 17:41
9

This is best done in the MenuItemDataBound.

protected void NavigationMenu_MenuItemDataBound(object sender, MenuEventArgs e)
{
    if (!Page.User.IsInRole("Admin"))
    {
        if (e.Item.NavigateUrl.Equals("/admin"))
        {
            if (e.Item.Parent != null)
            {
                MenuItem menu = e.Item.Parent;

                menu.ChildItems.Remove(e.Item);
            }
            else
            {
                Menu menu = (Menu)sender;

                menu.Items.Remove(e.Item);
            }               
        }
    }
}

Because the example used the NavigateUrl it is not language specific and works on sites with localized site maps.

Terence Golla
  • 1,018
  • 1
  • 13
  • 12
3

SIMPLE method may not be the best for all cases

        <%                
            if (Session["Utype"].ToString() == "1")
            {
        %>
        <li><a href="../forms/student.aspx"><i class="fa fa-users"></i><span>STUDENT DETAILS</span></a></li>   
        <li><a href="../forms/UserManage.aspx"><i class="fa fa-user-plus"></i><span>USER MANAGEMENT</span></a></li>
        <%
              }
            else
             {
        %>                      
        <li><a href="../forms/Package.aspx"><i class="fa fa-object-group"></i><span>PACKAGE</span></a></li>
        <%
             }                
        %>
Arun Prasad E S
  • 9,489
  • 8
  • 74
  • 87
2

Try this:

protected void Menu1_DataBound(object sender, EventArgs e)
{
   recursiveMenuVisit(Menu1.Items);
}

private void recursiveMenuVisit(MenuItemCollection items)
        {
            MenuItem[] itemsToRemove = new MenuItem[items.Count];
            int i = 0;

            foreach (MenuItem item in items)
            {
                if (item.NavigateUrl.Contains("Contact.aspx"))
                {
                    itemsToRemove[i] = item;
                    i++;
                }
                else
                {
                    if (item.ChildItems.Count > 0) recursiveMenuVisit(item.ChildItems);
                }
            }

            for(int j=0; j < i; j++)
            {
                items.Remove(itemsToRemove[j]);
            }
        }
1

To remove a MenuItem from an ASP.net NavigationMenu by Value:

public static void RemoveMenuItemByValue(MenuItemCollection items, String value)
{
   MenuItem itemToRemove = null;

   //Breadth first, look in the collection
   foreach (MenuItem item in items)
   {
      if (item.Value == value)
      {
          itemToRemove = item;
          break;
      }
   }

   if (itemToRemove != null)
   {
      items.Remove(itemToRemove);
      return;
   }


   //Search children
   foreach (MenuItem item in items)
   {
       RemoveMenuItemByValue(item.ChildItems, value);
   }
}

and helper extension:

public static RemoveMenuItemByValue(this NavigationMenu menu, String value)
{
   RemoveMenuItemByValue(menu.Items, value);
}

and sample usage:

navigationMenu.RemoveMenuItemByValue("UnitTests");

Note: Any code is released into the public domain. No attribution required.

Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
1

I have my menu in the site master page. I used the Page_Load() function to make the "Admin" menu item only visible to users with an Admin role.

using System;
using System.Linq;
using Telerik.Web.UI;
using System.Web.Security;



<telerik:RadMenu ID="menu" runat="server" RenderMode="Auto"  >
    <Items>
       <telerik:RadMenuItem    Text="Admin"  Visible="true" />
    </Items>
 </telerik:RadMenu>

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        RadMenuItem item = this.menu.FindItemByText("Admin");
        if (null != item)
        {
            if (Roles.IsUserInRole("Admin"))
            {
                item.Visible = true;   
            }
            else
            {
                item.Visible = false;
            }
        }
    }
}
DanLents
  • 21
  • 2
0

To find menu items in content page base on roles

 protected void Page_Load(object sender, EventArgs e)
{
   if (Session["AdminSuccess"] != null)
        {
           Menu mainMenu = (Menu)Page.Master.FindControl("NavigationMenu");

    //you must know the index of items to be removed first
    mainMenu.Items.RemoveAt(1);

    //or you try to hide menu and list items inside menu with css 
    // cssclass must be defined in style tag in .aspx page
    mainMenu.CssClass = ".hide";

        }   

}

<style type="text/css">
.hide
    {
        visibility: hidden;
     }
  </style>  
Dipen
  • 1,056
  • 1
  • 19
  • 36
0

You just have to remove the parent menu in the page init event.

    Protected Sub navMenu_Init(sender As Object, e As System.EventArgs) Handles navMenu.Init
    'Remove the admin menu for the norms
    Dim cUser As Boolean = HttpContext.Current.User.IsInRole("Admin")

    'If user is not in the Admin role removes the 1st menu at index 0
    If cUser = False Then
        navMenu.Items.RemoveAt(0)
    End If
End Sub
JSK NS
  • 3,346
  • 2
  • 25
  • 42
Brian
  • 1
  • 1