views:

747

answers:

3

I've seen some similar questions, but none that look like what I'm trying to do.

This is my current implementation w/out any security:

    <div id="menucontainer">
        <ul id="menu">              
            <li><%= Html.ActionLink("Main List", "Index", "AController")%></li>
            <li><%= Html.ActionLink("Product List", "Index", "BController")%></li>
            <li><%= Html.ActionLink("Company List", "Index", "CController")%></li>
            <li><%= Html.ActionLink("User List", "Index", "DController")%></li>
        </ul>
    </div>

This is fine, and the above works. I have [Authorize] Attributes setup on the Actions for CController and DController to prevent unauthorized access -- but I'd like to remove those items from the menu for users who don't have the correct Role, because when they see it and click on it and it tells them they don't have permission, they'll want it. If they don't know its there, thats just better for everyone involved...

Something like this is ultimatly the goal I'm trying to get at, but I'm looking for the more MVC Flavored aproach, where the "view" is "dumb":

    <div id="menucontainer">
        <ul id="menu">              
            <li><%= Html.ActionLink("Main List", "Index", "AController")%></li>
            <li><%= Html.ActionLink("Product List", "Index", "BController")%></li>
            <% If(Role = Roles.Admin) { %>
            <li><%= Html.ActionLink("Company List", "Index", "CController")%></li>
            <li><%= Html.ActionLink("User List", "Index", "DController")%></li>
            <% } %>
        </ul>
    </div>
+1  A: 

Did you here about MvcContrib's MenuBuilder?

If not, I suggest you'll take a look. The example project UI is a good way to start learn how to use it.

Mendy
+3  A: 

I have done something like this:

  • use a common base class for my controllers ('layer supertype')
  • in the BaseController, override OnActionExecuted (you could also define an ActionFilter attribute for this)

Something like this:

    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        // build list of menu items based on user's permissions, and add it to ViewData
        IEnumerable<MenuItem> menu = BuildMenu(); 
        ViewData["Menu"] = menu;
    }

In the master page:

    <% var model = ViewData["Menu"] as IEnumerable<MenuItem>; %>
    <% Html.RenderPartial("Menu", model); %>

(Note: in reality, I have a MasterViewModel that contains a.o. the menu model)

jeroenh
I presume ActionExecutedContext will have information about the current user? and I simply need to update all my controllers to inherit from this new base controller I've defined?
Nate Bross
yes, the ActionExecutedContext gives you access to a.o. the HttpContext
jeroenh
@jeroenh: What's a.o. ?
Pretzel
@Pretzel: among others
jeroenh
heh, I feel like a total n00b, but that's a new one to me. Thanks.
Pretzel
@jeroenh: So I started another thread referencing your answer here. Basically, I'm trying to flesh out your answer to a full class, but am struggling with getting it done right. Don't know if you want to toss in your 2 cents. http://stackoverflow.com/questions/2999918/how-to-discover-classes-with-authorize-attributes-using-reflection-in-c-or-h/2999979#2999979
Pretzel
A: 

Like @SD" said, you can create a "shiny" helper that with either render the link, or not, based on your security requirement.

Here is a good read on custom helpers (towards the bottom):

understanding-html-helpers on S. Walther's blog

Coov