allowing/disallowing asp:menu links based on user roles

The asp:menu control is pretty useful for making  menus and easy 'popout' links, but what if you don't want certain users to be able to navigate to some pages?

If you are using a menu control, it is likely because you want stuff to be easy.  But if you have certain links in there that you do not want a user to be able to click if they are not in certain roles, it is not that obvious what you can do to implement that.  First think you will notice is that MenuItems do not have IDs, so you can't access them in the 'normal' asp.net way.

 

What you have to do is to access them through Menu.FindItem(), and the then you can manipulate them.  But then there is the question, if they do not have IDs, how do I find the item?  The items are looked up by their Text property in a hierarchical manner.  To access things in a hierarchy, you need to first set your Menu's PathSeperator property; set this to a delimiter (I use a comma) that you will use to seperate levels.  Here is a sample menu with this implemented:

<asp:Menu ID="mnu" runat="server" PathSeparator=",">
    <Items>
        <asp:MenuItem Text="home" NavigateUrl="~/Default.aspx"  />
        <asp:MenuItem Text="A" NavigateUrl="#">
            <asp:MenuItem Text="A-1" NavigateUrl="#" />
            <asp:MenuItem Text="A-2" NavigateUrl="#" />
        </asp:MenuItem>
        <asp:MenuItem Text="B" NavigateUrl="#">
            <asp:MenuItem Text="B-1" NavigateUrl="#" />
            <asp:MenuItem Text="B-2" NavigateUrl="#" />
            <asp:MenuItem Text="B-3" NavigateUrl="#" />
        </asp:MenuItem>
    </Items>
</asp:Menu>

Once that is done, you now can simply iterate through the items (that you already put in a list, and disable those you do not want the non-admin user to have access to:

 string[] adminOnlyItems = {"A,A-1", "A,A-2", "B", "B-3"};
if (!User.IsInRole("admins"))
{
    foreach (string s in adminOnlyItems)
    {
        MenuItem mi = mnu.FindItem(s);
        mi.Enabled = false;
    }
}
Notice how the items are written out in a hierarchical string, written like this: <Level 1 Item> <delimeter> <Level 2 Item> <delimeter> <Level 3 Item> and so on with as many or as few levels as you are looking for.  Also notice that "B-3" is unnecessary in the adminOnlyItems array, as disabling "B" disables that whole path of links, anythign under "B" will now be unreachable.  Here is a working example (you must have roles enabled and an "admin" role for this to work):


Comments are closed