Asp.net mvc 3 带有层叠部分的嵌套布局

Asp.net mvc 3 带有层叠部分的嵌套布局,asp.net-mvc-3,razor,viewengine,Asp.net Mvc 3,Razor,Viewengine,我有一个MVC3站点,使用Razor作为它的视图引擎。我希望我的网站是可蒙皮的。大多数可能的外观都非常相似,可以从共享主布局派生 因此,我正在考虑这种设计: 但是,我希望能够在底层调用RenderSection\u Common.cshtml,并让它呈现在顶层定义的部分Detail.cshtml。这不起作用:RenderSection显然只渲染上一层定义的部分 当然,我可以定义每个皮肤中的每个部分。例如,如果\u Common需要为Detail中定义的部分调用RenderSection(“hd

我有一个MVC3站点,使用Razor作为它的视图引擎。我希望我的网站是可蒙皮的。大多数可能的外观都非常相似,可以从共享主布局派生

因此,我正在考虑这种设计:

但是,我希望能够在底层调用
RenderSection
\u Common.cshtml,并让它呈现在顶层定义的部分
Detail.cshtml
。这不起作用:
RenderSection
显然只渲染上一层定义的部分

当然,我可以定义每个皮肤中的每个部分。例如,如果
\u Common
需要为
Detail
中定义的部分调用
RenderSection(“hd”)
,我只需将其放置在每个
\u皮肤中即可:

@section hd {
    @RenderSection("hd")
}
这会导致一些代码重复(因为每个皮肤现在必须有相同的部分),并且通常感觉很凌乱。我对Razor还是个新手,似乎我遗漏了一些显而易见的东西

调试时,我可以在WebViewPage.SectionWritersStack中看到已定义节的完整列表。如果我能告诉RenderSection在放弃之前查看整个列表,它会找到我需要的部分。唉,SectionWriterStack是非公共的

或者,如果我可以访问布局页面的层次结构,并尝试在每个不同的上下文中执行RenderSection,我就可以找到我需要的部分。我可能遗漏了什么,但我看不出有什么办法


除了我已经概述的方法之外,还有其他方法可以实现这一目标吗?

这在今天使用公共API(除了使用节重新定义方法)实际上是不可能的。您可能会幸运地使用私有反射,但这当然是一种脆弱的方法。我们将在Razor的下一个版本中研究如何简化此场景

同时,以下是我就这一主题写的几篇博文:


这样做行吗?

我不确定这在MVC 3中是否可行,但在MVC 5中,我可以使用以下技巧成功地做到这一点:

~/Views/Shared/_Common.cshtml
中编写常见的HTML代码,如下所示:

<!DOCTYPE html>
<html lang="fa">
<head>
    <title>Skinnable - @ViewBag.Title</title>
</head>
<body>
@RenderBody()
</body>
</html>
现在您所要做的就是使用
\u Common.cshtml
作为所有皮肤的
布局。例如,在
~/Views/Shared/Skin1.cshtml
中:

@{
    Layout = "~/Views/Shared/_Common.cshtml";
}
@{
    Layout = "~/Views/Shared/_Common.cshtml";
}

<p>Something specific to Skin1</p>

@RenderBody()
如果运行上面的代码,您应该会得到一个包含
Skin1.cshtml
\u Common.cshtml


简而言之,您将为(皮肤)布局页面设置布局。

不确定这是否对您有帮助,但我编写了一些扩展方法来帮助从部分中“弹出”部分,这也适用于嵌套布局

在子布局/视图/局部中声明

@using (Html.Delayed()) {
    <b>show me multiple times, @Model.Whatever</b>
}

请参阅答案链接了解更多用例,例如即使在重复视图中声明,也只渲染一个延迟块,渲染特定的延迟块等。

感谢您的响应,我一直在使用此语法(如上所述)处理嵌套部分:@section hd{@RenderSection(“hd”)}。。。这对我来说非常有效,看起来我可以复制现有的嵌套母版页。我想我对这个问题有点误解,认为这样做行不通。这个问题和答案都很有帮助,我也同意在下一个版本的Razor中应该更容易做到这一点。您还应该允许局部视图也能够实现部分,这在目前是不受支持的。@Shrike我认为在这方面没有任何改变。您可以在上输入功能请求,也可以在@marcind上输入bug来查看我的答案。我想这就是OP的要求。对吗?MVC5出局了。有更新吗?Alirzea说他找到了一个解决方案,但它似乎与OPs问题不匹配,因为它根本没有参考章节。你在中间层使用这个吗?和你的差不多?如果是这样的话,在重新说明一个部分时,这会更方便,而不是解决问题,对吗?我只是想确定我理解,因为我来晚了。对我来说,这是唯一有效的解决办法。如果在基本布局中有条件地呈现一个部分,MVC将抛出一个运行时错误,除非该部分在中间层中有条件地定义(像这样)。谢谢@Randy!是否可以转发当前定义的所有部分?我对这种方法有问题,因为这些部分不可见。我找到了解决办法
    public ActionResult Index()
    {
        //....
        if (user.SelectedSkin == Skins.Skin1)
            return View("ViewName", "Skin1", model);
    }
@using (Html.Delayed()) {
    <b>show me multiple times, @Model.Whatever</b>
}
@Html.RenderDelayed();