作者:Steve Smith 和 Dave Brock
页面和视图经常共享视觉对象和编程元素。 本文演示如何实现以下内容:
- 使用常见布局。
- 共享指令。
- 在呈现页面或视图之前运行常见代码。
本文档讨论两种不同的 ASP.NET 核心 MVC 方法的布局: Razor 具有视图的页和控制器。 对于本主题,差异很小:
- Razor 页面位于 Pages 文件夹中。
- 带有视图的控制器使用 视图 文件夹存放视图。
什么是布局
大多数 Web 应用都有一个通用布局,可在用户从页面导航到页面时提供一致的体验。 布局通常包括常见的用户界面元素,例如应用标头、导航或菜单元素和页脚。
应用中许多页面也经常使用常见 HTML 结构,例如脚本和样式表。 所有这些共享元素都可以在 布局 文件中定义,然后可由应用中使用的任何视图引用。 布局可减少视图中的重复代码。
按照约定,ASP.NET Core 应用的默认布局命名 _Layout.cshtml。 使用模板创建的新 ASP.NET 核心项目的布局文件包括:
Razor 页面:
Pages/Shared/_Layout.cshtml
具有视图的控制器:
Views/Shared/_Layout.cshtml
布局为应用中的视图定义顶级模板。 应用不需要布局。 应用可以定义多个布局,不同的视图指定不同的布局。
以下代码显示了一个使用模板创建的项目中的布局文件,该项目具有控制器和视图:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - WebApplication1</title>
<environment include="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment exclude="Development">
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a asp-page="/Index" class="navbar-brand">WebApplication1</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-page="/Index">Home</a></li>
<li><a asp-page="/About">About</a></li>
<li><a asp-page="/Contact">Contact</a></li>
</ul>
</div>
</div>
</nav>
<partial name="_CookieConsentPartial" />
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© 2018 - WebApplication1</p>
</footer>
</div>
<environment include="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment exclude="Development">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery"
crossorigin="anonymous"
integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
crossorigin="anonymous"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
</script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment>
@RenderSection("Scripts", required: false)
</body>
</html>
指定布局
Razor 视图具有属性 Layout 。 单个视图通过设置此属性指定布局:
@{
Layout = "_Layout";
}
指定的布局可以使用完整路径(例如, /Pages/Shared/_Layout.cshtml 或 /Views/Shared/_Layout.cshtml)或部分名称(例如: _Layout) 。 提供部分名称时, Razor 视图引擎会使用其标准发现过程搜索布局文件。 首先搜索处理程序方法(或控制器)所在的文件夹,然后搜索Shared文件夹。 此发现过程与用于发现 部分视图的过程相同。
默认情况下,每个布局都必须调用 RenderBody。 无论 RenderBody 在何处调用,都会呈现视图的内容。
章节
布局可以通过调用来选择引用一个或多个RenderSection。 节提供了一种方法来组织应放置某些页面元素的位置。 每个调用 RenderSection 都可以指定该节是必需还是可选:
<script type="text/javascript" src="~/scripts/global.js"></script>
@RenderSection("Scripts", required: false)
如果未找到所需的节,则会引发异常。 单个视图通过@sectionRazor语法指定要在节中呈现的内容。 如果页面或视图定义了一个节,则必须呈现它(或将发生错误)。
Pages 视图中的示例 @section 定义 Razor :
@section Scripts {
<script type="text/javascript" src="~/scripts/main.js"></script>
}
在前面的代码中,scripts/main.js 被添加到某个页面或视图的 scripts 节中。 同一应用中的其他页面或视图可能不需要此脚本,也不会定义脚本部分。
以下标记使用 部分标记助手 来渲染 _ValidationScriptsPartial.cshtml:
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
前面的标记是通过 基架 Identity生成的。
页面或视图中定义的节仅在其即时布局页面中可用。 不能从部分、视图组件或视图系统的其他部分引用它们。
忽略部分
默认情况下,内容页中的正文和所有部分必须由布局页呈现。 视图 Razor 引擎通过跟踪正文和每个部分是否已被呈现来确保这一点。
若要指示视图引擎忽略正文或节,请调用 IgnoreBody 和 IgnoreSection 方法。
必须呈现或忽略页面中的 Razor 正文和每个部分。
导入共享指令
视图和页面可以使用 Razor 指令导入命名空间并使用 依赖项注入。 许多视图共享的指令可以在公共 _ViewImports.cshtml 文件中指定。 该文件 _ViewImports 支持以下指令:
@addTagHelper@removeTagHelper@tagHelperPrefix@using@model@inherits@inject@namespace
该文件不支持其他 Razor 功能,例如函数和节定义。
示例 _ViewImports.cshtml 文件:
@using WebApplication1
@using WebApplication1.Models
@using WebApplication1.Models.AccountViewModels
@using WebApplication1.Models.ManageViewModels
@using Microsoft.AspNetCore.Identity
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
_ViewImports.cshtml ASP.NET Core MVC 应用的文件通常放置在 Pages(或 Views)文件夹中。
_ViewImports.cshtml文件可以放置在任何文件夹中,在这种情况下,该文件将仅应用于该文件夹及其子文件夹中的页面或视图。
_ViewImports 从根级别开始处理文件,然后处理指向页面或视图本身位置的每个文件夹。
_ViewImports 在根级别指定的设置可以在文件夹级别覆盖。
例如,假设:
- 根级别
_ViewImports.cshtml文件包括@model MyModel1和@addTagHelper *, MyTagHelper1。 - 子文件夹
_ViewImports.cshtml文件包括@model MyModel2和@addTagHelper *, MyTagHelper2。
子文件夹中的页面和视图可以访问标记帮助器和 MyModel2 模型。
如果在文件层次结构中找到多个 _ViewImports.cshtml 文件,则指令的组合行为为:
-
@addTagHelper,@removeTagHelper:全部按顺序运行 -
@tagHelperPrefix:最靠近视图的视图替代任何其他视图 -
@model:最靠近视图的视图替代任何其他视图 -
@inherits:最靠近视图的视图替代任何其他视图 -
@using:包括所有内容;将忽略重复项 -
@inject:对于每个属性,离视图最近的属性将覆盖具有相同属性名称的任何其他属性
在每个视图之前运行代码
需要在每个视图或页面之前运行的代码应放在 _ViewStart.cshtml 文件中。 按照约定, _ViewStart.cshtml 该文件位于 Pages (或 Views)文件夹中。 列出的 _ViewStart.cshtml 语句在每个完整视图(不是布局和部分视图)之前运行。 与 ViewImports.cshtml 一样, _ViewStart.cshtml 是分层的。
_ViewStart.cshtml如果文件在视图或页面文件夹中定义,它将在页面(或视图)文件夹(如果有)的根目录中定义的文件之后运行。
示例 _ViewStart.cshtml 文件:
@{
Layout = "_Layout";
}
上面的文件指定所有视图都将使用 _Layout.cshtml 布局。
_ViewStart.cshtml 和 _ViewImports.cshtml 通常不放置在 /Pages/Shared(或 /Views/Shared)文件夹中。 这些文件的应用级版本应直接放置在 /Pages (或 /Views) 文件夹中。