Security Trimming for MVC Menus

I can’t believe I couldn’t really find anything on this… I wanted to have the Menus in my MVC (Model-View-Controller) ASP.NET web application honor the security that is in the SiteMapProvider. I found many posts but everything seemed so complicated. So I gave up and thought, “Let me see if I can solve it myself.”

Now I cannot find where I got the original code (I’m usually pretty good at commenting that in my code), but here is my current MenuHelper code for the Menu.

public static string Menu(this HtmlHelper helper)
{

    // Render each top level node
    if (!ReferenceEquals(SiteMap.CurrentNode, null))
    {
        return GetMenuString(helper, SiteMap.CurrentNode.ChildNodes);
    }
    else if (!ReferenceEquals(SiteMap.RootNode, null))
    {
        return GetMenuString(helper, SiteMap.RootNode.ChildNodes);
    }
    else
    {
        return string.Empty;
    }
}

private static string GetMenuString(HtmlHelper helper, SiteMapNodeCollection displayNodes)
{
    var sb = new StringBuilder();

    // Create opening unordered list tag
    sb.Append(“<ul class=’menu’>”);

    foreach (SiteMapNode node in displayNodes)
    {
        // Only Render the menu if the user has permission.
        if (UserIsAllowed(node))
        {

            if (SiteMap.CurrentNode == node)
                sb.AppendLine(“<li class=’selectedMenuItem’>”);
            else
                sb.AppendLine(“<li>”);

            sb.AppendFormat(“<a href='{0}’>{1}</a>”, node.Url, helper.Encode(node.Title));
            sb.AppendLine(“</li>”);
        }
    }

    // Close unordered list tag
    sb.Append(“</ul>”);

    return sb.ToString();
}

/// <summary>
///
 Returns true if the user is in one of the roles specified
/// by the SiteMapProvider.
/// </summary>
///
 <param name=”node”></param>
///
 <returns></returns>
internal static bool UserIsAllowed(SiteMapNode node)
{
    // If there are no roles, give all users access.
    if (node.Roles.Count == 0)
        return true;

    foreach (string role in node.Roles)
    {
        if (string.CompareOrdinal(“*”, role) == 0)
            return true;
        if (Roles.IsUserInRole(role))
            return true;
    }
    return false;
}

The lines that are NOT highlighted are ones I’m pretty sure I got from someplace else (perhaps on the ASP.NET MVC site). The highlighted is what I added to get security trimming to work for my menus.

I’m not confident in that code however… I’ve had a difficult time unit testing the SiteMapNodes… So there really aren’t any unit tests on this code.

3 Comments  »

RSS feed for comments on this post, TrackBack URI

Leave a Comment