ASP.NET MVC 特殊视图 - 部分视图和布局
有关 ASP.NET MVC 布局和部分视图的详细信息
引言
ASP.NET MVC 包含三个主要部分 - 模型 (Model)、视图 (View) 和控制器 (Controller)。模型代表业务实体或领域对象,并管理视图的状态。控制器负责应用程序逻辑以及模型和视图之间的通信。视图代表用户界面,它接收用户的输入并将其发送给控制器进行进一步处理。在本文中,我将介绍 ASP.NET MVC 中的特殊视图,如部分视图 (Partial Views) 和布局 (Layouts)。
Using the Code
要理解本文,读者应具备 ASP.NET MVC 的一些基本知识。即使您是 ASP.NET MVC 新手,也请放心,只需浏览这些文章,它将为您提供一些 ASP.NET MVC 的基础知识。有关更多信息,您可以参考链接 www.asp.net/mvc,这是 ASP.NET MVC 的官方网站。
在本文中,我将使用“学生管理”应用程序来演示 ASP.NET MVC 的功能。因此,您可以从这个源文件下载它,并参考它以便更好地理解。在开始运行应用程序之前,请阅读源存档中的 NuGet 包配置文档。
以下表格列出了本文中使用的一些辅助方法。ASP.NET MVC 提供了一组丰富的辅助扩展方法,用于生成 HTML 标记或与其相关的元素。ASP.NET Web Forms 应用程序有许多服务器控件来渲染标记,而辅助方法在 ASP.NET MVC 应用程序中则扮演着相同的角色。
辅助方法名称 | 描述 |
---|---|
@Html.ActionLink() |
渲染特定于操作的 URL,我们可以在锚标记中使用它来导航到视图。 |
@Html.Partial() |
将指定的部分视图渲染到当前视图中。 |
@RenderBody() |
在布局页面中渲染子视图的内容。 |
@RenderSection() |
渲染命名节的内容。 |
部分视图 (Partial Views)
部分视图 (Partial Views) 是特殊的视图,用于渲染视图内容的一部分。它类似于 Web Forms 应用程序中的用户控件,因此可以在多个视图中重用。我们可以通过将复杂的标记拆分为一个或多个部分视图来简化它。因此,部分视图提高了 ASP.NET MVC 应用程序中 HTML 标记的可维护性。
HTML 辅助方法提供了一个名为 Html.Partial
的扩展方法来渲染部分视图。下表显示了 Partial
方法的不同重载。
辅助方法名称 | 描述 |
---|---|
@Html.Partial(string partialViewName) |
将指定的部分视图内容渲染到引用的视图中。 |
@Html.Partial(string partialViewName,object model) |
将部分视图内容渲染到引用的视图中。Model 参数将模型对象传递给部分视图。 |
@Html.Partial(string partialViewName, ViewDataDictionary viewData) |
将部分视图内容渲染到引用的视图中。ViewData 参数将 ViewData 字典传递给部分视图。 |
@Html.Partial(string partialViewName,object model, ViewDataDictionary viewData) |
将部分视图内容渲染到引用的视图中。Model 参数将模型对象传递,ViewData 参数将 ViewData 字典传递给部分视图。 |
下一节将解释如何创建和使用部分视图。
-
右键单击 Shared 文件夹,然后选择 Add -> View,这将显示 Add View 对话框。
-
将名称输入为
_StudentItem
。 -
将 Template Engine 值保留为默认。
-
勾选 Create a strongly typed view,并从
Student Management.Models
命名空间中选择Student
。 -
勾选 Create as a partial view。现在 Add View 对话框将如下快照所示。
-
单击 **Add** 按钮。
Visual Studio 将在 Shared 文件夹下创建一个名为 _StudentItem.cshtml 的文件。打开学生索引视图,它包含显示所有学生的标记,其模块类型为 IEnumerable<Student>
。在这里,我们将一部分标记移动到部分视图中,并将其链接到索引视图。以下步骤解释了如何做到这一点。
- 将以下标记部分移动到
_StudentItem
部分视图。<td> @Html.DisplayFor(modelItem => item.Name) </td> <td> @Html.DisplayFor(modelItem => item.BranchName) </td> <td> @Html.DisplayFor(modelItem => item.CourseName) </td> <td> @Html.DisplayFor(modelItem => item.Gender) </td> <td> @Html.DisplayFor(modelItem => item.Address) </td> <td> @Html.ActionLink("Edit", "Edit", new { id = item.StudentId }) | @Html.ActionLink("Details", "Details", new { id = item.StudentId }) | @Html.ActionLink("Delete", "Delete", new { id = item.StudentId }) </td>
- 查找并替换
modelItem
和item
为 model,但操作链接项除外。对于操作链接项,您应该将item
替换为Model
,而不是model
。 - 在索引视图中添加
@Html.Partial("_StudentItem",item)
,其中第一个参数是部分视图的名称,item 是部分视图的模型对象。现在索引视图中的新标记将如下所示。@foreach (var item in Model) { <tr> @Html.Partial("_StudentItem",item) </tr>
- 构建应用程序并在浏览器中进行测试。输出没有变化,但我们将一部分数据列表标记移到了部分视图中。这是一个解释部分视图概念的简单示例;您可以在各种场景中使用它。
布局
布局 (Layout) 是 ASP.NET MVC 中的另一种特殊视图类型,它类似于 ASP.NET Web Forms 中的母版页。布局用于在整个应用程序中保持 UI 元素和主题的一致性。Razor 布局引入了两个新概念,称为 Web 页面主体 (web page body) 和 Web 页面节 (web page section)。Web Body 只是在特定位置渲染引用视图的内容。Web 页面节用于在布局中声明多个节,这些节由引用视图定义。它有两种形式,一种是没有 required 标志,另一种是有 required 标志;默认情况下,required 标志为 true
。当 required 标志为 true
时,引用视图必须为特定命名节提供定义。
Web Body 概念使用 @RenderBody
方法在放置它的位置渲染引用视图的内容。当 Razor 调用此方法时,它会执行所有引用视图(嵌套布局和视图)并渲染视图的 HTML 输出。我们不能在同一个布局中使用此方法一次以上。@RenderSection()
用于在布局中声明一个命名节,引用视图使用 @section
块定义内容。@RenderSection()
方法接受两个参数:一个是要渲染的节的名称,另一个是 required 标志;当 required 标志为 true
时,引用视图必须提供定义,否则它是可选的。还有一个名为 IsSectionDefined
的辅助方法,用于从布局检查是否在任何引用视图中为特定命名节提供了定义。
ASP.NET MVC 模板提供了一个默认布局,名为 _Layout.cshtml/.vbhtml,您可以在 Shared 文件夹下找到此文件。默认情况下,所有视图都使用默认布局,如果您在视图中搜索 layout 属性,您将找不到它,但它仍然引用默认布局。_ViewStart.cshtml 实现了这一功能,它将默认布局分配给所有未显式分配布局的视图,并且它将在视图开始之前执行,这是放置所有视图所需的一些通用代码的好地方。
以下步骤将解释如何创建和使用布局
- 右键单击 **Shared** 文件夹,然后选择 Add -> View,这将显示 Add View 对话框。
- 将 View Name 输入为 **_Admin**。
- 将 Template Engine 值保留为默认。
- 将 Create strongly typed view 和 Create Partial view 保持为未选中状态。
- 取消选中 Use a layout or master page。
- 单击 Add 按钮。现在 Add View 对话框将如下快照所示。
现在将在 shared 文件夹下创建一个名为 **_Admin.cshtml** 的文件。根据需要修改布局内容,但请确保已放置 @RenderBody()
和 @RenderSection()
方法。其中 @RenderBody()
是必需的,而 @RenderSection
是可选的。
对于学生管理后台控制器的布局,我们将使用以下标记
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>@ViewBag.Title - Admin</title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body id="admin">
<header>
<div id="topbar" class="topbar">
<div class="float-left">
<nav>
<ul id="menu">
<li>@Html.ActionLink("Home", "Index", "Admin")</li>
<li>@Html.ActionLink("Branch", "Index", "Branch")</li>
<li>@Html.ActionLink("Course", "Index", "Course")</li>
<li>@Html.ActionLink("Student", "Index", "Student")</li>
</ul>
</nav>
</div>
<div class="float-right">
<section id="login">
@Html.Partial("_LoginPartial")
</section>
</div>
</div>
</header>
<div id="body">
@RenderSection("featured", required: false)
<section class="content-wrapper main-content clear-fix">
@RenderBody()
</section>
</div>
<footer>
<div class="content-wrapper">
<div class="float-left">
<p>© @DateTime.Now.Year - Student Management Company</p>
</div>
</div>
</footer>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/student")
@RenderSection("scripts", required: false)
</body>
</html>
现在为 Branch
、Course
和 Student
创建新的控制器,并使用上述新布局。请遵循以下步骤。
- 右键单击 controller 文件夹,然后选择 **Add Controller**,这将显示以下对话框来创建控制器。
- 将 Controller Name 输入为
BranchController
。 - 选择 Template 为 MVC with read/ write actions and views with Entity Framework。
- 从
StudentManagement.Models
命名空间中选择 Model Class 为Branch
。 - 从
StudentManagement.Models
命名空间中选择 Data Context Class 为AdminContext
。 - 单击 Advanced Option Button。
- 确保 Use a layout or a master page 已勾选。
- 从 Shared 文件夹中选择 Layout 为 _Admin.cshtml。
- 单击 Advanced Option 对话框上的 **OK** 按钮。
- 单击 Add Controller 对话框上的 Add 按钮。现在 Controller 对话框将如下快照所示。
Visual Studio 将在 Controller 和 Views 文件夹下创建以下文件夹和文件。
控制器 (Controller)
- BranchController
视图
- Branch
- Create.cshtml
- Details.cshtml
- Delete.cshtml
- Edit.cshtml
- Index.cshtml
要为 Course
和 Student
等其他模块创建控制器,请为每个模块重复以上步骤。
为所有模块创建控制器后,在 _Admin.cshtml 的 header 部分添加以下链接。
@Html.ActionLink("Branch", "Index", "Branch")
@Html.ActionLink("Course", "Index", "Course")
@Html.ActionLink("Student", "Index", "Student")
如果您已经为上述模块拥有视图,那么只需打开所有视图文件,并在每个视图的顶部添加 Layout 属性,值为 ~/Views/Shared/_Admin.cshtml。
Layout 属性
Layout = "~/Views/Shared/_Admin.cshtml";
以上一行显式设置了 Layout
属性为新布局,因此默认布局将不适用。如果您仔细观察所有视图内容,一些视图为 Scripts 命名节提供了定义,而另一些视图则没有。但没有视图为 featured 节提供任何定义,因为它的 required 标志设置为 false
,因此此节的定义是可选的。Razor @section
标签用于在引用视图中定义特定命名节的定义。
现在我们可以测试带新布局的应用程序了,因此请构建应用程序并导航到 Admin console,然后检查新布局的输出。它看起来将如下快照所示。
嵌套布局
ASP.NET MVC 允许我们创建嵌套布局,通过它您可以为现有布局创建新的子布局。当您想进一步拆分布局时,这将非常有用。一个重要的事情是父标记可以传递给子布局,但命名节(@RenderSection()
)不会传递。因此,您可能会遇到错误,如无法在子布局中找到 RenderSection
。您可以通过在子布局中重新声明所有父节来修复此问题。
以下步骤将展示如何创建和使用嵌套布局
- 右键单击 Shared 文件夹,然后选择 Add -> View,这将显示 Add View 对话框。
- 将 View Name 输入为
_AdminNestedLayout
。 - 将 Template Engine 值保留为默认。
- 将 Create strongly typed view 和 Create Partial view 保持为未选中状态。
- 将 Use a layout or master page 选择为 _Admin.cshtml。
- 单击 Add 按钮。现在 Add View 对话框将如下快照所示。
Visual Studio 将在 shared 文件夹下创建一个文件,名为 _AdminNestedLayout.cshtml。它将包含以下内容。
@{
ViewBag.Title = "_AdminNestedLayout";
Layout = "~/Views/Shared/_Admin.cshtml";
}
<h2>_AdminChildLayout</h2>
从标记中删除 ViewBag.Title
属性,并用以下内容替换现有内容。
@{
Layout = "~/Views/Shared/_Admin.cshtml";
}
<h2 class="hr">@ViewBag.Title</h2>
@RenderBody()
此嵌套布局的目的是为所有管理员视图提供唯一的动作标题格式。现在我们需要将此新布局链接到所有管理员视图,请继续并对所有管理员视图的 Layout 属性进行以下修改。
Layout = "~/Views/Shared/_ AdminNestedLayout.cshtml";
在所有管理员视图中, wherever you find the <h2>Action name</h2>
markup,请将其删除,并稍微修改您的标题显示方式。现在运行应用程序并检查结果,在索引视图中您不会遇到任何问题,但当您尝试导航到任何模块的 Create New 链接时,您会收到以下错误,
The following sections have been defined but have not been rendered for the layout page "~/Views/Shared/_AdminNestedLayout.cshtml": "Scripts".
上述错误表明当前视图中使用的 Script 节未在嵌套布局中声明,父布局 _Admin.cshtml
已经为 Scripts 定义了 @RenderSection
,但仍然无法在嵌套布局中识别它。原因是父节不会自动传递给子布局,除非在子/嵌套布局中重新声明这些节。一旦您在 _AdminNestedLayout.cshtml 中重新声明了 scripts 节,上述错误就会消失。以下代码片段显示了在嵌套布局中重新声明 scripts 节。
_AdminNestedLayout.cshtml
@section scripts{
@RenderSection("scripts",false)
}
我们可以使用 IsSectionDefined
方法来检查引用视图中是否已定义了命名节的定义,使用此方法,我们可以将上述 razor 块更改为以下内容:
<!-- define a named section -->
<!-- Check whether the referencing view has given the definition for this named section -->
@if (IsSectionDefined("Scripts"))
{
@section scripts{
<!-- re-declare the parent section to extend to referencing view -->
@RenderSection("scripts",false)
}
}
构建并运行应用程序,然后检查结果。它看起来将如下快照所示。
结论
在本文中,我们讨论了布局和部分视图是什么,如何创建和使用它们。我们还学习了一些在使用它们时应该遵循的重要事项。请在评论部分提供您的宝贵反馈。感谢您花时间阅读本文。我希望它能为您提供一些有用的信息。