Razor中的布局与Web窗体中的母版页具有相同的目的。它们使您可以为网站指定布局,并切出一些占位符部分以实现视图。
例如,这是一个具有主体部分和页脚部分的简单布局。
<!DOCTYPE html>
<html>
<head><title>Sample Layout</head>
<body>
<div>@RenderBody()</div>
<footer>@RenderSection("Footer")</footer>
</body>
</html>
为了使用此布局,您的视图可能看起来像。
@{
Layout = "MyLayout.cshtml";
}
<h1>Main Content!</h1>
@section Footer {
This is the footer.
}
注意,我们使用@section
语法为已定义的页脚节指定内容。
但是,如果我们还有其他未为页脚部分指定内容的视图怎么办?他们将抛出一个异常,指出未定义“脚”部分。
要使一个部分可选,我们需要调用重载 RenderSection
并指定false
该required
参数。
<!DOCTYPE html>
<html>
<head><title>Sample Layout</head>
<body>
<div>@RenderBody()</div>
<footer>@RenderSection("Footer", false)</footer>
</body>
</html>
但是,如果在视图中未定义该节的情况下定义一些默认内容,那会更好吗?
好吧,这是一种方法。这有点丑陋,但可以。
<footer>
@if (IsSectionDefined("Footer")) {
RenderSection("Footer");
}
else {
<span>This is the default yo!</span>
}
</footer>
那是丑陋的代码。如果只有一种方法可以编写该版本 RenderSection
,则可以接受一些Razor标记作为该方法的参数。
模板化剃刀代表救援!看,我告诉你这些事情会派上用场。
我们可以在上面编写一个扩展方法WebPageBase
来封装这部分难看的样板代码。这是实现。
public static class Helpers {
public static HelperResult RenderSection(this WebPageBase webPage,
string name, Func<dynamic, HelperResult> defaultContents) {
if (webPage.IsSectionDefined(name)) {
return webPage.RenderSection(name);
}
return defaultContents(null);
}
}
比这段代码更有趣的是我们现在如何使用它。我的布局现在可以执行以下操作以定义页脚部分:
<footer>
@this.RenderSection("Footer", @<span>This is the default!</span>)
</footer>
那更干净!但是我们可以做得更好。请注意,这个丑陋的this
关键字怎么了?这是必要的,因为当您在当前类上编写扩展方法时,必须使用this
kewyord对其进行调用 。
还记得我写过有关如何更改Razor视图的基本类型的文章吗?在这种情况下,这确实很方便。
我们可以做的是编写我们自己的自定义基本页面类型(例如CustomWebViewPage
我在该博客文章中使用的 类),然后将RenderSection
上面的方法添加 为该类的实例方法。我将其留给读者练习。
最终结果将使您执行以下操作:
<footer>
@RenderSection("Footer", @<span>This is the default!</span>)
</footer>
非常漂亮!
您可能想知道为什么我们不仅仅在Razor中包含此功能。我的猜测是我们想要但只是时间用光了。希望这将在下一版的Razor中实现。