tags:

views:

357

answers:

2

We are beginning the process of moving from Web Forms to MVC for all of our new applications. I am working on porting our Master Page over and am trying to satisfy the requirements that we need a single master page to be used by all applications. The primary navigation for the application needs to be in a menu within the master page. Accomplishing this was easy, the hard part is that each application may need to determine what to display in the menu using a unique set of rules. Some apps can simply say, here's the menu structure to use via something like a SiteMap. Others need to determine what is displayed in the menu based on what roles the user has, this can also be handled easily with a SiteMap. The situation that I'm struggling with is that some apps need to generate the menus based on the roles the user has, but also on the data on which they are working. i.e. The same user may have different option in the menu for a page if they are working on object 'foo' than they do if working on object 'bar'.

What I've done at this point, is I've created an HtmlHelper that is called by the master page view and takes a list of objects of a custom type and returns an unordered list that is styled by a jQuery plugin to display the menu. The list of objects the helper method takes are passed to the view using the ViewData dictionary. Currently, the value of this ViewData node is set within the constructor of each controller. This allows each page, and potentially each method, to set a different menu without having to set the value in each action method, unless its needed. I have also created a class that parses a SiteMap and returns the list of items needed to build the menu. This class is what I'm using to set the ViewData value in the controller. The idea being that if an application needed more control of how the menu data was generated, they could create their own class to generate the data as long as it returns a list of the correct type of objects.

This solution seems to work fine so far, it just doesn't 'feel' right for some reason. I'm hoping that I can either get some ideas of better way to do this or some reassurance that this is a valid approach to solving this problem.

A: 

In the book I am reading (Pro ASP.NET MVC Framework by Apress) they use Html.RenderAction for the menu in the masterpage. I am a Asp.net MVC novice so maybe somebody else can give more info about this.

You can download the sourcecode at apress.com though so maybe that could help.

Pickels
+1  A: 

If it is something that will be on every page, do something like this:

Create a base controller:

public class MyBaseController : Controller

Have this controller get the data it needs and send that data in the ViewData["menu"] to the View. Then have all your controllers inherit from this one:

public class HomeController : MyBaseController

In the Master Page, loop through your ViewData and create your menu.

(I did something like this for my sub-menu which displayed a list of categories.)

Martin
Just wanted to comment that this is probably as best a solution as I know, given the scenario that each page/action may need to manipulate the menu. (Otherwise I think Html.RenderAction makes a little more sense, but only when the menu is defined by something more static - like a user role - and does not change per page)
Kurt Schindler
I thought about creating a base controller, but since its possible that each page/action could need a different menu source, that seemed like it wouldn't work as well.
Hamman359
If each page/action will dictate a new menu, then create a base controller with a method that takes the controller and action, then have that spit out the ViewData.
Martin