asp.net core系列 42 Web 应用 分部视图
一.分部视图
对于mvc 视图和 razor pages 页面,都有分部视图功能。通常将 mvc 视图和 razor pages 页面统称为“标记文件”,下面会常提到该名词。使用分部视图的优势包括:(1) 将大型标记文件分解为更小的组件。(2) 减少跨标记文件中,常见标记内容的重复。
建议:(1)不应使用分部视图来维护常见布局元素,常见布局元素应在 _layout.cshtml 文件中指定,比如页头、页尾。(2)当需要呈现复杂逻辑或代码执行的应该使用视图组件。
1.1 声明分部视图
分部视图是在 views 文件夹 (mvc) 或 pages 文件夹 (razor pages) 中维护的 .cshtml 标记文件。在 asp.net core mvc 中,控制器的 viewresult 能够返回视图或分部视图。 在 asp.net core 2.2 中 razor pages 的pagemodel 可以返回 partialviewresult分部视图。
分部视图不会运行 _viewstart.cshtml页,这涉及到布局以后再讲。分部视图的文件名通常以下划线 _
开头,没有.cshtml.cs文件。
1.2 引用分部视图
在标记文件中,有多种方法可引用分部视图。 建议应用程序使用以下异步呈现方法之一:(1) 分部标记帮助程序。(2) 异步 html 帮助程序。 不建议使用同步html 帮助程序, 因为可能会出现死锁的情况, 同步方法以后版本中会删除,这里不再介绍。
(1) 分部标记帮助程序
分部标记帮助程序会异步呈现内容,并使用类似 html 的语法:
<partial name="_partialname" />
当存在文件扩展名时,标记帮助程序会引用分部视图,该视图必须与调用分部视图的标记文件位于同一文件夹中:
<partial name="_partialname.cshtml" />
以下示例从应用程序根目录引用分部视图。 以 (~/
) 或 (/
) 开头的路径,指代应用程序根目录:
razor 页面cshtml <partial name="~/pages/folder/_partialname.cshtml" /> <partial name="/pages/folder/_partialname.cshtml" />
mvc cshtml <partial name="~/views/folder/_partialname.cshtml" /> <partial name="/views/folder/_partialname.cshtml" />
使用相对路径的分部视图 <partial name="../account/_partialname.cshtml" />
(2) 异步 html 帮助程序
使用 html 帮助程序时,最佳做法是使用 partialasync,同步是使用partial(不建议使用同步)。partialasync 返回包含在 task<tresult> 中的 ihtmlcontent 类型。通过@await来引用该方法。
razor 页面cshtml @await html.partialasync("~/pages/folder/_partialname.cshtml") @await html.partialasync("/pages/folder/_partialname.cshtml")
mvc cshtml @await html.partialasync("~/views/folder/_partialname.cshtml") @await html.partialasync("/views/folder/_partialname.cshtml")
也可以使用 renderpartialasync 呈现分部视图。 此方法不返回 ihtmlcontent。它将呈现的输出,直接流式传输到响应, 因此在某些情况下它可提供更好的性能。 因为该方法不返回结果,所以必须在 razor 代码块内调用它:
@{ await html.renderpartialasync("_authorpartial"); }
1.3 分部视图发现
如果按名称(无文件扩展名)引用分部视图,则按所述顺序搜索以下位置:
(1) razor 页面
1.当前正在执行页面的文件夹
2.该页面文件夹上方的目录图
3./shared
4./pages/shared
5./views/shared
(2) mvc
1./areas/<area-name>/views/<controller-name>
2./areas/<area-name>/views/shared
3./views/shared
4./pages/shared
1.4 通过分部视图访问数据
实例化分部视图时,它会获得父视图(主视图)的 viewdata
字典的副本。 在分部视图内,对数据所做的更新不会保存到父视图中。 对分部视图中的 viewdata
更改,会在分部视图返回时丢失。
以下示例演示如何将 viewdatadictionary(viewdata
字典)的实例传递给分部视图:
@await html.partialasync("_partialname", customviewdata)
还可将模型(实体对象)传入分部视图。 模型可以是自定义对象。
@await html.partialasync("_partialname", model)
二. 演示
下面演示一个razor的分部视图(mvc的参考官网示例)。示例中pages/articlesrp/readrp.cshtml是主视图,pages/shared/_authorpartialrp.cshtml是第一个分部视图,传入“作者”。pages/articlesrp/_articlesectionrp.cshtml 是第二个分部视图,传入viewdata字典和section模型二个参数,这二个参数是partialasync的方法重载。 三个文件结构如下:
(1) 创建实体类
public class article { public string title { get; set; } public string authorname { get; set; } public string publicationdate { get; set; } public list<articlesection> sections { get; set; } } public class articlesection { public string title { get; set; } public string content { get; set; } }
(2)主视图
public class readrpmodel : pagemodel { public article article { get; set; } public void onget() { article = new article() { title = "来自 <共享分部视图文件路径> 的分部视图", authorname = "abraham lincoln", publicationdate= "1863 年 11 月 19 日中午 12:00:00", sections = new list<articlesection>() { new articlesection (){ title="第一节索引", content="八十七年前..." }, new articlesection (){ title="第二节索引", content="如今,我们正在进行一场伟大的内战,考验着......" }, new articlesection (){ title="第三节索引", content="然而,从更广泛的意义上说,我们无法奉献..." }, } }; } }
@page @model readrpmodel <h2>@model.article.title</h2> @model.article.publicationdate @* 将作者名字传到 pages\shared\_authorpartialrp.cshtml*@ <p>---------------------------------第一个分部视图/views/shared/_authorpartial.cshtml</p> @await html.partialasync("../shared/_authorpartialrp.cshtml", model.article.authorname) <p></p> @* loop over the sections and pass in a section and additional viewdata to the strongly typed pages\articlesrp\_articlesectionrp.cshtml partial view. *@ <p>---------------------------------第二个分部视图/views/shared/_articlesection.cshtml</p> @{ var index = 0; @foreach (var section in model.article.sections) { @await html.partialasync("_articlesectionrp", section, new viewdatadictionary(viewdata) { { "index", index } }) index++; } }
(3) 分部视图 _authorpartialrp.cshtm
@* 将传过来的string类型映射*@ @model string <div> <h3>@model</h3> </div>
(4) 分部视图 _articlesectionrp.cshtml
@using studyrazordemo.models; @* 将传过来的对象映射到articlesection中*@ @model articlesection <h3>@model.title index: @viewdata["index"]</h3> <div> @model.content </div> <p></p>
启动程序,运行http://localhost:42921/articlesrp/readrp,显示如下:
参考资料
推荐阅读
-
asp.net core系列 41 Web 应用 MVC视图
-
asp.net core系列 45 Web应用 模型绑定和验证
-
asp.net core系列 44 Web应用 布局
-
asp.net core系列 43 Web应用 Session分布式存储(in memory与Redis)
-
ASP.NET Core Web 应用程序系列(二)- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)
-
ASP.NET Core Web 应用程序系列(一)- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入(MVC当中应用)
-
asp.net core系列 42 Web 应用 分部视图
-
asp.net core系列 40 Web 应用MVC 介绍与详细示例
-
ASP.NET Core Web 应用程序系列(五)- 在ASP.NET Core中使用AutoMapper进行实体映射
-
ASP.NET Core Web 应用程序系列(四)- ASP.NET Core 异步编程之async await