Khyron Khyron - 2 months ago 34
C# Question

RenderPartial with model from _Layout.cshtml

One of the overloads for

Html.RenderPartial
allows you to pass in a model. How can you make use of that from
_Layout.cshtml
?

I have a model prepared with everything I need. I just can't see how to make it accessible to the Layout.

_Layout.cshtml

<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
<nav>
@{ Html.RenderPartial("pMenu", menu); }
</nav>
...


pMenu.cshtml

The partial view for the menu. Hopefully this makes it clear that the menu is dynamic and really does need a model passed to it.

@model MyApplication.Menu

@foreach (KeyValuePair<string, MyApplication.MenuGroup> group in Model.group)
{
if (group.Key != "default")
{
<div>@group.Key.ToString()</div>
}
<ul>
@foreach (MyApplication.MenuItem item in group.Value.items.Values)
{
<li>
@if (item.isCurrent)
{
<span class="@item.Icon">@item.LinkText</span>
}
else
{
@Html.ActionLink(item.LinkText, item.Action, item.Controller, item.RouteValues, new { @class = @item.Icon })

}
@if (null != item.subItems)
{
<ul class="tree">
@foreach (MyApplication.SubItem subitem in item.subItems)
{
<li>
@if (subitem.isCurrent)
{
<span>@subitem.LinkText</span>
}
else
{
@Html.ActionLink(subitem.LinkText, subitem.Action, subitem.Controller, subitem.RouteValues, null)
}
</li>
}
</ul>
}
</li>
}
</ul>
}


Where is the menu instantiated?

public class MainController : Controller
{
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
menu = new Menu(requestContext.RouteData.Values);


Background information

This is an intranet application. It does not have the typical hard-coded menu options of "Home", "About", "Contact". Most of the menu is created from user-maintained database records. The menu is individualised to the user. No two users will have the same menu items. Eg: A manager gets a menu item for each of their staff.

The menu model also handles other factors that make the menu "dynamic" such as:


  • identifying whether the requested page matches a given menu item (by route data) (for styling)

  • adding extra menu items based on roles

  • sometimes adding sub-menus for the current context



This seems similar to #Render partial with a model in Layout View but I think that question went off the rails by referring to session.

Disclaimer: I'm an experienced programmer but relatively new to C# and asp.NET MVC.

Answer

ViewData to the rescue.

_Layout.cshtml

@{ Html.RenderPartial("pMenu", ViewData["menu"]); }

MainController

menu = new Menu(requestContext.RouteData.Values);
ViewData["menu"] = menu;

Modifying menu after this point still works. I'm not sure why, but I'll take it.

See also Best way to do global viewdata in an area of my ASP.NET MVC site?

Comments