Razor视图中动态定义的内容部分

时间:2011-06-14 17:31:35

标签: asp.net-mvc asp.net-mvc-3 razor

我正在尝试实现一个想法,我必须允许为我的MVC 3 Razor站点动态生成用户定义的部分。

模板看起来像这样

<div class="sidebar">
     @RenderSection("Sidebar", false)
</div>
<div class="content">
     @RenderSection("MainContent", false)
     @RenderBody()
</div>

使用以下代码添加视图会给出我期望的结果

DefineSection("MainContent", () =>
{
    this.Write("Main Content");
});
DefineSection("Sidebar", () =>
{
    this.Write("Test Content");
});

输出:

<div class="sidebar">Test Content </div>
<div class="content">Main Content <p>Rendered body from view</p></div>

看着这个,创建一个模型似乎很容易 Dictionary<SectionName, Dictionary<ControlName, Model>>

var sectionControls = new Dictionary<string, Dictionary<string, dynamic>>();
        sectionControls.Add("MainContent", new Dictionary<string, dynamic>()
        { 
            {"_shoppingCart", cart}
        });
        sectionControls.Add("Sidebar", new Dictionary<string, dynamic>() 
        { 
            { "_headingImage", pageModel.HeadingImage },
            { "_sideNav", null }
        });
        pageModel.SectionControls = sectionControls;

因此,上面的代码声明了两个模板部分(带有购物车的“MainContent”和带有图像和导航的“侧边栏”。

所以现在我的视图包含了如此呈现输出的代码

foreach(KeyValuePair<string,Dictionary<string,dynamic>> section in Model.SectionControls)
    {
        DefineSection(section.Key, () =>
        {
            foreach (KeyValuePair<string, dynamic> control in section.Value)
            {
                RenderPartialExtensions.RenderPartial(Html, control.Key, control.Value);
            }
        });
  }

现在,当我运行此代码时,两个部分都包含相同的内容!单步执行代码显示加载路径如下

操作返回,上面的代码在View中运行,LayoutTemlpate开始加载。当在布局模板中为这两个部分调用RenderSection时,视图再次运行!对我来说似乎更奇怪的是,最终结果是“HeadingImage”和“SideNav”最终都出现在Sidebar和MainContent部分。 MainContent部分不包含购物车,它包含侧边栏部分的副本。

<div class="sidebar">
<h2><img alt=" " src="..."></h2>
..nav..
</div>
<div class="content">
<h2><img alt=" " src="..."></h2>
..nav..
<p>Rendered body from view</p>
</div>

注释掉Controller中两个部分定义中的一个导致另一个部分是唯一的项目(但它仍然是重复的!)

之前是否有人遇到此问题或知道可能导致此行为的限制?

编辑:非常好。感谢您的联系!我正在为剃须刀支持的新版resharper而受伤。

1 个答案:

答案 0 :(得分:6)

您的lambda表达式共享相同的section变量 当调用lambda时,变量的当前值是最后一节。

You need to declare a separate variable inside the loop

foreach(KeyValuePair<string,Dictionary<string,dynamic>> dontUse in Model.SectionControls)
{
    var section = dontUse;

    DefineSection(section.Key, () =>
    {
        foreach (KeyValuePair<string, dynamic> control in section.Value)
        {
            RenderPartialExtensions.RenderPartial(Html, control.Key, control.Value);
        }
    });
}