tags:

views:

2740

answers:

4

I have a database menu structure which I would like to add to the site.master file.

I’ve looked at other questions on StackOverflow but cannot get this to work on my website.

How do I add a User Control to the Site.Master file?

Menu.ascx

<%foreach (MainMenuSort mainMenuSort in (List<MainMenuSort>)ViewData["MainMenuSortListDisplay"])
      { %>
         <li><%= Html.Encode(mainMenuSort.MainMenuId.MainMenuName)%></li>
         <%foreach (SubMenuSort subMenuSort in (List<SubMenuSort>)ViewData["SubMenuSortListDisplay"])
           {%>
            <%if (mainMenuSort.MainMenuId.Id == subMenuSort.SubMenuId.MainMenu.Id)
              { %>
              <li><%= Html.Encode(subMenuSort.SubMenuId.SubMenuName)%></li>
            <%} %>
         <%} %>
      <%}%>
+3  A: 

You need to use the Html.RenderPartial method in your master page.

You will need to set the MainMenuSortListDisplay and SubMenuSortListDisplay view data keys in whatever action is calling the view that uses your master page.

In your master use this

<% Html.RenderPartial("~/Views/Shared/Menu.ascx");

The path needs to be the app relative path to the control's folder. Typically these go under Shared. You can make the structure how you want below the Shared folder.

To make this technique stronger, use a strongly typed partial. In the question you would perhaps make a new class (MenuModel) with two generic collections as properties and place it in the models folder of the application. Then in the model's constructor call a method that populates the lists.

public class MenuModel
{
   public IEnumerable<MainMenuSort> OuterList {get; set;}
   public IEnumerable<SubMEnuSort> InnerList {get; set;}
   public MenuModel()
   {
       VoidThatFillsTheInnerAndOuterList();
   }

This will mean that you can do this in your controller

public ActionResult ShowAForm()
{
   ViewData["MenuPartialData"] = new MenuModel();
   return View();
}

Having set this key, your master page can use the overload of RenderPartial, like this

<% Html.RenderPartial(
    "~/View/Shared/Menu.ascx", 
    (MenuModel)ViewData["MenuPartialData"]); %>

This assumes that your partial is strongly typed to the MenuModel class. Then in the partial you can use the model which rewrites your code slightly

<% foreach (MainMenuSort mainMenuSort in Model.OuterList) { %>
     <li><%= Html.Encode(mainMenuSort.MainMenuId.MainMenuName)%></li>
     <% foreach (SubMenuSort subMenuSort in Model.InnerList) {%>            
        <%if (mainMenuSort.MainMenuId.Id == subMenuSort.SubMenuId.MainMenu.Id)  
        { %>              
           <li><%= Html.Encode(subMenuSort.SubMenuId.SubMenuName)%></li>
      <%} %>
     <%} %>      
    <%}%>

Hope that helps

Mark Dickinson
Thank you. Just learning ASP.NET MVC and have added <% Html.RenderPartial("~/Views/Shared/Menu.ascx");%> to the site.master page but do not understand what you mean by: "You will need to set the MainMenuSortListDisplay and SubMenuSortListDisplay view data keys in whatever action is calling the view that uses your master page."
Roslyn
You call the page using an ActionResult method in your controller class. In this method you will need to set the ViewData keys e.g.ViewData["SubMenuSortListDisplay"] = SomeListPreferablyFromYourModel
Mark Dickinson
Shout back if you're stil stuck :-)
Mark Dickinson
Sorry, still cannot get the menu to display. Could you post any links to example code? Thanks.
Roslyn
Best thing to do is to make a partial without any data driven stuff in, and get that to display, check that your controller is calling the correct view and that the view uses the master page. Then put the data stuff back in and set the ViewData keys. Do this using objects that you initialise in the Action, so if its a list initialise the objects in it like this, new MyList(){ new MyObj(){...}, new MyObj{...} };This should prove that your control handles the data, so then if that is ok, the problem is in your data. I'll have a look for an example.
Mark Dickinson
Check this post http://stackoverflow.com/questions/143571/partials-asp-net-mvc
Mark Dickinson
Thanks. I have have managed to get the the Menu.ascx to display without any data. I have also managed to get the menu to display with the correct data in a separate view/controller. So I know the data is correct. I think I'm misunderstanding how the menu.ascx file in the shared folder knows which controller to use?
Roslyn
Hi Roslyn, the ascx should not know which controller to use. The controller renders the view (aspx), which uses the master (.master). If you have things in the master page (i.e. ascx) that require view data, it is your controller that sets it. So where you set the view data in the other controller that works, copy that code into your action that calls the page with the master page. Pages and Controls should not be deciding where to get data from in MVC :-)
Mark Dickinson
What about this answer, you can pass the view data explicity to the partial. http://stackoverflow.com/questions/233261/pass-viewdata-as-member-from-other-viewdata-to-renderpartial-makes-the-first-null
Mark Dickinson
Thanks. I'm now getting an System.NullReferenceException: Object reference not set to an instance of an object for (List<MainMenuSort>)ViewData["MainMenuSortListDisplay"]).
Roslyn
In your controller you are going to need to have a method (MyMethod()) that gets the List<MainMenuSort> and then sets it to the ViewData key, e.g. ViewData["MainMenuSortListDisplay"] = MyMethod();
Mark Dickinson
Thank you for posting example code. The menu is now displaying in the site.master page. I used a Partial Request within the Site.master page and followed http://blog.codeville.net/2008/10/14/partial-requests-in-aspnet-mvc/ . Thanks.
Roslyn
Good luck Roslyn :)
Mark Dickinson
A: 

Try something like

<% Html.RenderPartial("Menu") %>

EDIT: Corrected a typo

mhenrixon
A: 

You could also do it as a HTMLHelper and in the MasterPage just call <%= Html.Menu() %>. Then in your HTMLHelper you have the code to get the database records and loop through them. Here is a link I found to get you started. Note my comments as there is a bug in the code example provided. I'm still having issues handling subitems of menus, I guess I need a recursive function or something??

Jon
Thanks for posting the link. I used a Partial Request and followed http://blog.codeville.net/2008/10/14/partial-requests-in-aspnet-mvc/
Roslyn
A: 

With the help of this link. I was able to display a menu in the site.master page.

Roslyn