ASP.NET Core 中的分部视图Partial views in ASP.NET Core

本文内容

作者:Steve SmithMaher JENDOUBIRick AndersonScott Sauber

分部视图是 Razor 标记文件 (.cshtml),它在另一个标记文件呈现的输出中呈现 HTML 输出。

在开发 MVC 应用程序(其中标记文件称为“视图”)或 Razor Pages 应用程序(其中标记文件称为“页”)时,均会使用术语“分部视图”。本主题通常将 MVC 视图和 Razor Pages 页面称为“标记文件”。

查看或下载示例代码如何下载

何时使用分部视图When to use partial views

分部视图是执行下列操作的有效方式:

  • 将大型标记文件分解为更小的组件。

在由多个逻辑部分组成的大型复杂标记文件中,在分部视图中处理隔开的每个部分是有利的。标记文件中的代码是可管理的,因为标记仅包含整体页面结构和对分部视图的引用。

  • 减少跨标记文件中常见标记内容的重复。

当在标记文件中使用相同的标记元素时,分部视图会将重复的标记内容移到一个分部视图文件中。在分部视图中更改标记后,它会更新使用该分部视图的标记文件呈现的输出。

不应使用分部视图来维护常见布局元素。常见布局元素应在 _Layout.cshtml 文件中指定。

请勿使用需要复杂呈现逻辑或代码执行来呈现标记的分部视图。使用视图组件而不是分部视图。

声明分部视图Declare partial views

分部视图是在 Views文件夹 (MVC) 或 Pages文件夹 (Razor Pages) 中维护的 .cshtml标记文件。

在 ASP.NET Core MVC 中,控制器的 ViewResult 能够返回视图或分部视图。在 Razor Pages 中,PageModel 可以返回表示为 PartialViewResult 对象的分部视图。引用分部视图部分介绍了引用和呈现分部视图。

与 MVC 视图或页面呈现不同,分部视图不会运行 _ViewStart.cshtml。有关 _ViewStart.cshtml 的详细信息,请参阅 ASP.NET Core 中的布局

分部视图的文件名通常以下划线 (_) 开头。虽然未强制要求遵从此命名约定,但它有助于直观地将分部视图与视图和页面区分开来。

分部视图是在 Views文件夹中维护的 .cshtml标记文件。

控制器的 ViewResult 能够返回视图或分部视图。引用分部视图部分介绍了引用和呈现分部视图。

与 MVC 视图呈现不同,分部视图不会运行 _ViewStart.cshtml。有关 _ViewStart.cshtml 的详细信息,请参阅 ASP.NET Core 中的布局

分部视图的文件名通常以下划线 (_) 开头。虽然未强制要求遵从此命名约定,但它有助于直观地将分部视图与视图区分开来。

引用分部视图Reference a partial view

在 Razor Pages PageModel 中使用分部视图Use a partial view in a Razor Pages PageModel

在 ASP.NET Core 2.0 或 2.1 中,以下处理程序方法将 AuthorPartialRP.cshtml 分部视图呈现给响应_

  1. public IActionResult OnGetPartial() =>
  2. new PartialViewResult
  3. {
  4. ViewName = "_AuthorPartialRP",
  5. ViewData = ViewData,
  6. };

在 ASP.NET Core 2.2 或更高版本中,处理程序方法也可以调用 Partial 方法来生成 PartialViewResult 对象:

  1. public IActionResult OnGetPartial() =>
  2. Partial("_AuthorPartialRP");

在标记文件中使用分部视图Use a partial view in a markup file

在标记文件中,有多种方法可引用分部视图。我们建议应用程序使用以下异步呈现方法之一:

在标记文件中,有两种方法可引用分部视图:

我们建议应用程序使用异步 HTML 帮助程序

分部标记帮助程序Partial Tag Helper

分部标记帮助程序要求 ASP.NET Core 2.1 或更高版本。

分部标记帮助程序会异步呈现内容并使用类似 HTML 的语法:

  1. <partial name="_PartialName" />

当存在文件扩展名时,标记帮助程序会引用分部视图,该视图必须与调用分部视图的标记文件位于同一文件夹中:

  1. <partial name="_PartialName.cshtml" />

以下示例从应用程序根目录引用分部视图。以波形符斜杠 (~/) 或斜杠 (/) 开头的路径指代应用程序根目录:

Razor 页面

  1. <partial name="~/Pages/Folder/_PartialName.cshtml" />
  2. <partial name="/Pages/Folder/_PartialName.cshtml" />

MVC

  1. <partial name="~/Views/Folder/_PartialName.cshtml" />
  2. <partial name="/Views/Folder/_PartialName.cshtml" />

以下示例引用使用相对路径的分部视图:

  1. <partial name="../Account/_PartialName.cshtml" />

有关详细信息,请参阅 ASP.NET Core 中的部分标记帮助程序

异步 HTML 帮助程序Asynchronous HTML Helper

使用 HTML 帮助程序时,最佳做法是使用 PartialAsyncPartialAsync 返回包含在 IHtmlContent 中的 Task<TResult> 类型。通过在等待的调用前添加 @ 字符前缀来引用该方法:

  1. @await Html.PartialAsync("_PartialName")

当存在文件扩展名时,HTML 帮助程序会引用分部视图,该视图必须与调用分部视图的标记文件位于同一文件夹中:

  1. @await Html.PartialAsync("_PartialName.cshtml")

以下示例从应用程序根目录引用分部视图。以波形符斜杠 (~/) 或斜杠 (/) 开头的路径指代应用程序根目录:

Razor 页面

  1. @await Html.PartialAsync("~/Pages/Folder/_PartialName.cshtml")
  2. @await Html.PartialAsync("/Pages/Folder/_PartialName.cshtml")

MVC

  1. @await Html.PartialAsync("~/Views/Folder/_PartialName.cshtml")
  2. @await Html.PartialAsync("/Views/Folder/_PartialName.cshtml")

以下示例引用使用相对路径的分部视图:

  1. @await Html.PartialAsync("../Account/_LoginPartial.cshtml")

或者,也可以使用 RenderPartialAsync 呈现分部视图。此方法不返回 IHtmlContent它将呈现的输出直接流式传输到响应。因为该方法不返回结果,所以必须在 Razor 代码块内调用它:

  1. @{
  2. await Html.RenderPartialAsync("_AuthorPartial");
  3. }

由于 RenderPartialAsync 流式传输呈现的内容,因此在某些情况下它可提供更好的性能。在性能起关键作用的情况下,使用两种方法对页面进行基准测试,并使用生成更快响应的方法。

同步 HTML 帮助程序Synchronous HTML Helper

PartialRenderPartial 分别是 PartialAsyncRenderPartialAsync 的同步等效项。但不建议使用同步等效项,因为可能会出现死锁的情况。同步方法针对以后版本中的删除功能。

重要

如果需要执行代码,请使用视图组件,而不是使用分部视图。

调用 PartialRenderPartial 会导致 Visual Studio 分析器警告。例如,使用 Partial 会产生以下警告消息:


使用 IHtmlHelper.Partial 可能会导致应用程序死锁。 考虑使用 <分部> 标记帮助程序或 IHtmlHelper.PartialAsync。


将对 @Html.Partial 的调用替换为 @await Html.PartialAsync分部标记帮助程序有关分部标记帮助程序迁移的详细信息,请参阅从 HTML 帮助程序迁移

分部视图发现Partial view discovery

如果按名称(无文件扩展名)引用分部视图,则按所述顺序搜索以下位置:

Razor 页面

  • 当前正在执行页面的文件夹
  • 该页面文件夹上方的目录图
  • /Shared
  • /Pages/Shared
  • /Views/Shared
    MVC
  • /Areas/<Area-Name>/Views/<Controller-Name>
  • /Areas/<Area-Name>/Views/Shared
  • /Views/Shared
  • /Pages/Shared
  • /Areas/<Area-Name>/Views/<Controller-Name>
  • /Areas/<Area-Name>/Views/Shared
  • /Views/Shared

以下约定适用于分部视图发现:

  • 当分部视图位于不同的文件夹中时,允许使用具有相同文件名的不同分部视图。
  • 当按名称(无文件扩展名)引用分部视图且分部视图出现在调用方的文件夹和 文件夹中时,调用方文件夹中的分部视图会提供分部视图。如果调用方文件夹中不存在分部视图,则会从 文件夹中提供分部视图。文件夹中的分部视图称为“共享分部视图”或“默认分部视图”。
  • 可以链接分部视图—如果调用没有形成循环引用,则分部视图可以调用另一个分部视图。相对路径始终相对于当前文件,而不是相对于文件的根视图或父视图。

备注

分部视图中定义的Razor section 对父标记文件不可见。section 仅对定义它时所在的分部视图可见。

通过分部视图访问数据Access data from partial views

实例化分部视图时,它会获得父视图的 字典的副本ViewData在分部视图内对数据所做的更新不会保存到父视图中。在分部视图中的 ViewData 更改会在分部视图返回时丢失。

以下示例演示如何将 ViewDataDictionary的实例传递给分部视图:

  1. @await Html.PartialAsync("_PartialName", customViewData)

还可将模型传入分部视图。模型可以是自定义对象。你可以使用 PartialAsync(向调用方呈现内容块)或 RenderPartialAsync(将内容流式传输到输出)传递模型:

  1. @await Html.PartialAsync("_PartialName", model)

Razor 页面

示例应用程序中的以下标记来自 Pages/ArticlesRP/ReadRP.cshtml 页面。此页包含两个分部视图。第二个分部视图将模型和 ViewData 传入分部视图。ViewDataDictionary 构造函数重载可用于传递新 ViewData 字典,同时保留现有的 ViewData 字典。

  1. @model ReadRPModel
  2. <h2>@Model.Article.Title</h2>
  3. @* Pass the author's name to Pages\Shared\_AuthorPartialRP.cshtml *@
  4. @await Html.PartialAsync("../Shared/_AuthorPartialRP", Model.Article.AuthorName)
  5. @Model.Article.PublicationDate
  6. @* Loop over the Sections and pass in a section and additional ViewData to
  7. the strongly typed Pages\ArticlesRP\_ArticleSectionRP.cshtml partial view. *@
  8. @{
  9. var index = 0;
  10. foreach (var section in Model.Article.Sections)
  11. {
  12. await Html.PartialAsync("_ArticleSectionRP",
  13. section,
  14. new ViewDataDictionary(ViewData)
  15. {
  16. { "index", index }
  17. });
  18. index++;
  19. }
  20. }

Pages/Shared/_AuthorPartialRP.cshtml 是 ReadRP.cshtml 标记文件引用的第一个分部视图:

  1. @model string
  2. <div>
  3. <h3>@Model</h3>
  4. This partial view from /Pages/Shared/_AuthorPartialRP.cshtml.
  5. </div>

Pages/ArticlesRP/_ArticleSectionRP.cshtml 是 ReadRP.cshtml 标记文件引用的第二个分部视图:

  1. @using PartialViewsSample.ViewModels
  2. @model ArticleSection
  3. <h3>@Model.Title Index: @ViewData["index"]</h3>
  4. <div>
  5. @Model.Content
  6. </div>

MVC

示例应用中的以下标记显示Views/Articles/Read.cshtml 视图。此视图包含两个分部视图。第二个分部视图将模型和 ViewData 传入分部视图。ViewDataDictionary 构造函数重载可用于传递新 ViewData 字典,同时保留现有的 ViewData 字典。

  1. @model PartialViewsSample.ViewModels.Article
  2. <h2>@Model.Title</h2>
  3. @* Pass the author's name to Views\Shared\_AuthorPartial.cshtml *@
  4. @await Html.PartialAsync("_AuthorPartial", Model.AuthorName)
  5. @Model.PublicationDate
  6. @* Loop over the Sections and pass in a section and additional ViewData to
  7. the strongly typed Views\Articles\_ArticleSection.cshtml partial view. *@
  8. @{
  9. var index = 0;
  10. foreach (var section in Model.Sections)
  11. {
  12. await Html.PartialAsync("_ArticleSection",
  13. section,
  14. new ViewDataDictionary(ViewData)
  15. {
  16. { "index", index }
  17. });
  18. index++;
  19. }
  20. }

Views/Shared/_AuthorPartial.cshtml 是 Read.cshtml 标记文件引用的第一个分部视图:

  1. @model string
  2. <div>
  3. <h3>@Model</h3>
  4. This partial view from /Views/Shared/_AuthorPartial.cshtml.
  5. </div>

Views/Articles/_ArticleSection.cshtml 是 Read.cshtml 标记文件引用的第二个分部视图:

  1. @using PartialViewsSample.ViewModels
  2. @model ArticleSection
  3. <h3>@Model.Title Index: @ViewData["index"]</h3>
  4. <div>
  5. @Model.Content
  6. </div>

在运行时,分部视图在父标记文件呈现的输出中呈现,而父标记文件本身在共享的 _Layout.cshtml 内呈现。第一个分部视图呈现文章作者的姓名和发布日期:


Abraham Lincoln


来自 <共享分部视图文件路径> 的分部视图。
1863 年 11 月 19 日中午 12:00:00


第二个分部视图呈现文章的各部分:


第一节索引:0


八十七年前…


第二节索引:1


如今,我们正在进行一场伟大的内战,考验着……


第三节索引:2


然而,从更广泛的意义上说,我们无法奉献…


其他资源Additional resources