问题
I try to put a dynamic menu (load from xml) in my Layout but I've got a StackOverflowException in PartialController.cs/MainMenu()
I don't understand why my code throw a StackOverflowException because I don't have a loop (or I don't see it !).
Layout.cshtml :
....
<div id="menu">
@if (Request.IsAuthenticated)
{
Html.RenderAction("MainMenu", "Partial");
}
</div>
....
MainMenu.cshtml :
@model Geosys.BoT.Portal.POC.Business.Menu
@foreach (var item in Model.Nodes)
{
<ul>
<li>
@item.Name
<ul>
@foreach (var subItem in item.Links)
{
<li>
@Html.ActionLink(subItem.Name, subItem.Action, subItem.Controller)
</li>
}
</ul>
</li>
</ul>
}
PartialController.cs :
[ChildActionOnly]
public ActionResult MainMenu()
{
var menu = new Menu { Nodes = new List<NodeMenu>() };
var xmlData = System.Web.HttpContext.Current.Server.MapPath("~/Content/navigation.xml");
if (xmlData == null)
{
throw new ArgumentNullException("xmlData");
}
var xmldoc = new XmlDataDocument();
var fs = new FileStream(xmlData, FileMode.Open, FileAccess.Read);
xmldoc.Load(fs);
var xmlnode = xmldoc.GetElementsByTagName("node");
for (var i = 0; i <= xmlnode.Count - 1; i++)
{
var xmlAttributeCollection = xmlnode[i].Attributes;
if (xmlAttributeCollection != null)
{
var nodeMenu = new NodeMenu { Name = xmlAttributeCollection["title"].Value, Links = new List<LinkMenu>() };
if (xmlnode[i].ChildNodes.Count != 0)
{
for (var j = 0; j < xmlnode[i].ChildNodes.Count; j++)
{
var linkMenu = new LinkMenu();
var xmlNode = xmlnode[i].ChildNodes.Item(j);
if (xmlNode != null)
{
if (xmlNode.Attributes != null)
{
linkMenu.Name = xmlNode.Attributes["title"].Value;
linkMenu.Action = xmlNode.Attributes["action"].Value;
linkMenu.Controller = xmlNode.Attributes["controller"].Value;
linkMenu.Key = xmlNode.Attributes["key"].Value;
nodeMenu.Links.Add(linkMenu);
}
}
}
}
menu.Nodes.Add(nodeMenu);
}
}
return View(menu);
}
navigation.xml:
<nodes>
<node title="User Management">
<link title="Create User" action="CreateUser" controller="UserManagement" key="UM_CREATEUSER" />
<link title="Users List" action="UsersList" controller="UserManagement" key="UM_USERSLIST" />
<link title="Import Users" action="ImportUsers" controller="UserManagement" key="UM_IMPORTUSERS" />
</node>
</nodes>
EDIT : This is the detail of the exception (there's no StackTrace):
System.StackOverflowException was unhandled An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll
{Cannot evaluate expression because the current thread is in a stack overflow state.}
In the Call Stack, I see the line "Html.RenderAction("MainMenu", "Partial");" constantly called but I don't know why.
回答1:
There is an infinite loop here. The problem is that you do this in your Layout:
@Html.RenderAction("MainMenu", "Partial");
And then in your Action you do this:
return View(menu);
When you call return View()
your view is rendered, including your layout. So your layout then renders your @Html.RenderAction(...)
again... which calls your View()... which renders your Layout... etc.. etc.. etc..
You solve this by returning a PartialView()
which does not render your Layout, or by rendering a view with Layout set to Null. This is the primary difference between a View()
and a PartialView()
, Layout rendering.
来源:https://stackoverflow.com/questions/27298137/asp-net-mvc-stackoverflowexception-loading-dynamic-menu-from-xml-in-layout