2014-12-04 73 views
0

从XML加载动态菜单我试图把一个动态菜单(从XML负载)在我的布局,但我在PartialController.cs/MainMenu的()ASP.NET MVC StackOverflowException在布局

我有一个StackOverflowException不明白为什么我的代码抛出一个StackOverflowException,因为我没有一个循环(或者我没有看到它!)。

Layout.cshtml:

.... 
<div id="menu"> 
    @if (Request.IsAuthenticated) 
    { 
     Html.RenderAction("MainMenu", "Partial"); 
    } 
</div> 
.... 

MainMenu.cshtml:

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> 

编辑: 这是异常的细节(有没有堆栈跟踪):

System.StackOverflowException了未处理 类型的未处理的异常 'System.StackOverflowException' 出现在mscorlib.dll

{因为当前线程堆栈溢出状态无法计算表达式。}

调用堆栈,我看行“Html.RenderAction( “MainMenu”,“部分”);“不断地打电话,但我不知道为什么。

+2

你是什么意思,我在这段代码中看到3个循环。 1'foreach'循环和2'for'循环。如果您可以从溢出异常中添加堆栈跟踪,这可能有助于缩小堆栈溢出的位置。 – danludwig 2014-12-04 15:49:47

+0

您可以尝试使用LINQ表达式来获取选定节点而不是循环的列表(如果需要帮助,请告诉我)。附注:最后在'stackoverflow.com'上看到了'stackoverflow exception' :)。 – 2014-12-04 15:54:19

+0

当我说“我没有看到一个循环”时,我的意思是我没有看到递归循环。我知道我有3个循环,但stackoverflow异常不在这些循环中。多次调用MainMenu()方法。我会把堆栈跟踪放在main中。 – 2014-12-05 08:24:19

回答

2

这里有一个无限循环。问题是,你在你的布局做到这一点:

@Html.RenderAction("MainMenu", "Partial"); 

然后在你的行动,你这样做:

return View(menu); 

当你调用return View()您的视图显示,包括您的布局。因此,您的布局然后再次呈现您的@Html.RenderAction(...) ...哪些调用您的视图()...哪些呈现您的布局...等等..等..

您解决此问题通过返回PartialView()哪渲染您的布局,或者通过渲染布局设置为Null的视图。这是View()PartialView()布局渲染之间的主要区别。

+0

我在其他地方发现了这个解决方案,但你是唯一解释原因的解决方案。谢谢! – leahcimp 2015-04-02 00:27:54