ASP.NET Core 中文文档 第四章 MVC(3.9)视图组件
作者: Rick Anderson
翻译: 娄宇(Lyrics)
校对: 高嵩
章节:
介绍视图组件
视图组件是 ASP.NET Core MVC 中的新特性,与局部视图相似,但是它们更加的强大。视图组件不使用模型绑定,只取决于调用它时所提供的数据。视图组件有以下特点:
- 渲染一个块,而不是整个响应
- 在控制器和视图之间同样包含了关注点分离和可测试性带来的好处
- 可以拥有参数和业务逻辑
- 通常从布局页调用
视图组件可以用在任何需要重复逻辑且对局部视图来说过于复杂的情况,比如:
- 动态导航菜单
- 标签云 (需要从数据库查询时)
- 登录面板
- 购物车
- 最近发表的文章
- 一个典型博客的侧边栏内容
- 会在所有页面渲染的登录面板,根据用户登录状态显示登录或者注销
一个 视图组件 包含两个部分,类(通常派生自 ViewComponent
)和它返回的结果(通常是一个视图)。类似控制器,视图组件可以是 POCO 类型,但是大部分开发者想要使用派生自 ViewComponent
的方法和属性。
创建视图组件
这个章节包含创建视图组件的高级需求。在稍后的文章中,我们将详细地检查每一个步骤,并创建一个视图组件。
视图组件类
一个视图组件类可以由以下任何一个方式创建:
- 派生自
ViewComponent
- 使用
[ViewComponent]
特性装饰一个类,或者这个类的派生类。 - 创建一个类,并以 ViewComponent 作为后缀。
如同控制器一样,视图组件必须是公开的,非嵌套的,以及非抽象的类。视图组件名称是类名并去掉“ViewComponent”后缀。也可以通过 ViewComponentAttribute.Name 属性进行明确的指定。
一个视图组件类:
视图组件方法
视图组件在 InvokeAsync
方法中中定义逻辑,并返回 [IViewComponentResultIViewComponentResult。参数直接来自视图组件的调用,而不是来自模型绑定。视图组件从来不直接处理请求。通常视图组件初始化模型并通过调用 View方法传递它到视图。总之,视图组件方法有以下特点:
- 定义一个
InvokeAsync
方法并返回IViewComponentResult
- 通常初始化模型并通过调用ViewComponent View方法传递它到视图
- 参数来自调用方法,而不是 HTTP,没有模型绑定
- 不可直接作为 HTTP 终结点,它们从你的代码中调用(通常在视图中)。视图组件从不处理请求
- 重载的签名,而不是当前 HTTP 请求中的任何细节
视图搜索路径
运行时对视图的搜索路径如下:
- Views/<controller_name>/Components/<view_component_name>/<view_name>
- Views/Shared/Components/<view_component_name>/<view_name>
视图组件默认的视图名是 Default,意味着通常你的视图文件会命名为 Default.cshtml。当你创建视图组件结果或者调用 View
方法的时候,你可以指定不同的视图名。
我们建议你命名视图文件为 Default.cshtml 并且使用 Views/Shared/Components/<view_component_name>/<view_name> 路径。在这个例子中使用的 PriorityList
视图组件使用了 Views/Shared/Components/PriorityList/Default.cshtml 这个路径。
调用视图组件
要使用视图组件,从视图中调用 @Component.InvokeAsync("视图组件名", <匿名类型参数>)
。参数将传递给 InvokeAsync
方法。在文章中开发的 PriorityList
视图组件被 Views/Todo/Index.cshtml 视图文件调用。在下面,使用了两个参数调用 InvokeAsync
方法:
@await Component.InvokeAsync("PriorityList", new { maxPriority = 2, isDone = false })
从控制器直接调用视图组件
视图组件通常从视图中调用,但是你也可以从控制器方法中直接调用。当视图组件没有像控制器一样定义终结点时,你可以简单实现一个控制器的 Action ,并使用一个 ViewComponentResult作为返回内容。
在这例子中,视图组件通过控制器直接调用:
public IActionResult IndexVC()
{
return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}
演练:创建一个简单的视图组件
下载,生成并测试启动代码。这是一个简单的项目,使用一个 Todo
控制器来显示 Todo 项列表。
添加一个视图组件类
创建一个 ViewComponents 文件夹并添加下面的 PriorityListViewComponent
类。
using Microsoft.AspNet.Mvc;
using Microsoft.Data.Entity;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ViewComponentSample.Models;
namespace ViewComponentSample.ViewComponents
{
public class PriorityListViewComponent : ViewComponent
{
private readonly ToDoContext db;
public PriorityListViewComponent(ToDoContext context)
{
db = context;
}
public async Task<IViewComponentResult> InvokeAsync(
int maxPriority, bool isDone)
{
var items = await GetItemsAsync(maxPriority, isDone);
return View(items);
}
private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)
{
return db.ToDo.Where(x => x.IsDone == isDone &&
x.Priority <= maxPriority).ToListAsync();
}
}
}
代码注释:
- 视图组件类可以被放在项目中 任何 文件夹内。
- 因为类命名为
PriorityListViewComponent
,以 ViewComponent 作为后缀结束,在运行时会从视图中使用 "PriorityList" 字符串来引用组件类。我会在后面详细解释。 [ViewComponent]
特性可以改变被用来引用视图组件的名字。比如,我们可以命名类为XYZ
,然后应用ViewComponent
特性:
[ViewComponent(Name = "PriorityList")]
public class XYZ : ViewComponent
- 上面的
[ViewComponent]
特性告知视图组件选择器在寻找与组件相关的视图时使用名字PriorityList
,并且在从视图中引用组件类时使用 "PriorityList" 字符串。我会在后面详细解释。 - 组件使用依赖注入使得数据上下文可用。
InvokeAsync
暴露一个可以在视图中调用的方法,并且它可以接受任意数量的参数。InvokeAsync
方法返回没有完成并优先级小于等于maxPriority
的ToDo
项的集合。
创建视图组件 Razor 视图
- 创建 Views/Shared/Components 文件夹。这个文件夹 必须 命名为 Components。
- 创建 Views/Shared/Components/PriorityList 文件夹。这个文件夹必须和视图组件类名字匹配,或者是类名去掉后缀(如果我们遵循了约定并且使用 ViewComponent 作为类名后缀)。如果你使用
ViewComponent
特性,类名需要匹配特性中指定的名字。 - 创建一个 Views/Shared/Components/PriorityList/Default.cshtml Razor 视图。
@model IEnumerable<ViewComponentSample.Models.TodoItem>
<h3>Priority Items</h3>
<ul>
@foreach (var todo in Model)
{
<li>@todo.Name</li>
}
</ul>
Razor 视图取一组 TodoItem
并显示它们。如果视图组件的 InvokeAsync
方法没有传递视图名(就像我们例子中),按照约定会使用 Default 作为视图名。在教程的后面部分,我会告诉你如何传递视图的名称。为特定控制器重写默认的样式,添加一个视图到特定控制器的视图文件夹(比如 Views/Todo/Components/PriorityList/Default.cshtml)。
如果视图组件是特定控制器的,你可以添加到特定控制器文件夹(Views/Todo/Components/PriorityList/Default.cshtml)。
- 在 Views/Todo/index.cshtml 文件底部添加一个
div
包含调用 PriorityList 组件:
}
</table>
<div >
@await Component.InvokeAsync("PriorityList", new { maxPriority = 2, isDone = false })
</div>
标记 @Component.InvokeAsync
展示了调用视图组件的语法。第一个参数是我们想要调用的组件名。随后的参数传递给组件。InvokeAsync
可以接受任意数量的参数。
下面的图片显示了 Priority 项:
你也可以从控制器直接调用视图组件:
public IActionResult IndexVC()
{
return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}
指定视图名
一个复杂的视图组件在某些条件下可能需要指定非默认的视图。下面的代码展示如何从 InvokeAsync
方法中指定 "PVC" 视图。更新 PriorityListViewComponent
类中的 InvokeAsync
方法。
public async Task<IViewComponentResult> InvokeAsync(int maxPriority, bool isDone)
{
string MyView = "Default"; // 手动高亮
// If asking for all completed tasks, render with the "PVC" view. // 手动高亮
if (maxPriority > 3 && isDone == true) // 手动高亮
{ // 手动高亮
MyView = "PVC"; // 手动高亮
} // 手动高亮
var items = await GetItemsAsync(maxPriority, isDone);
return View(MyView, items);
}
复制 Views/Shared/Components/PriorityList/Default.cshtml 文件到一个视图中并命名为 Views/Shared/Components/PriorityList/PVC.cshtml。添加一个标题到 PVC 视图来表明正在使用此视图。
@model IEnumerable<ViewComponentSample.Models.TodoItem>
<h2> PVC Named Priority Component View</h2> // 手动高亮
<h4>@ViewBag.PriorityMessage</h4>
<ul>
@foreach (var todo in Model)
{
<li>@todo.Name</li>
}
</ul>
更新 Views/TodoList/Index.cshtml
</table>
<div>
@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
</div>
运行应用程序并验证 PVC 视图。
如果 PVC 视图没有渲染,请验证你是否使用 4 或者更高 priority 参数来调用视图组件。
检查视图路径
改变 priority 参数到 3 或者更低,使得不返回优先级视图。
暂时重命名 Views/Todo/Components/PriorityList/Default.cshtml 为 Temp.cshtml。
测试应用程序,你将得到以下错误:
An unhandled exception occurred while processing the request.
InvalidOperationException: The view 'Components/PriorityList/Default'
was not found. The following locations were searched:
/Views/ToDo/Components/PriorityList/Default.cshtml
/Views/Shared/Components/PriorityList/Default.cshtml.
Microsoft.AspNetCore.Mvc.ViewEngines.ViewEngineResult.EnsureSuccessful()复制 Views/Shared/Components/PriorityList/Default.cshtml 到 Views/Todo/Components/PriorityList/Default.cshtml。
添加一些标记到 Todo 视图组件视图来表明视图是来自 Todo 文件夹。
测试 非共享 组件视图。
避免魔法字符串
如果你想编译时安全你可以用类名替换硬编码视图组件名。创建视图组件不以 "ViewComponent" 作为后缀:
using Microsoft.AspNet.Mvc;
using Microsoft.Data.Entity;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ViewComponentSample.Models;
namespace ViewComponentSample.ViewComponents
{
public class PriorityList : ViewComponent // 手动高亮
{
private readonly ToDoContext db;
public PriorityList(ToDoContext context) // 手动高亮
{
db = context;
}
public async Task<IViewComponentResult> InvokeAsync(
int maxPriority, bool isDone)
{
var items = await GetItemsAsync(maxPriority, isDone);
return View(items);
}
private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)
{
return db.ToDo.Where(x => x.IsDone == isDone &&
x.Priority <= maxPriority).ToListAsync();
}
}
}
添加一个 using
语句到你的 Razor 视图文件并使用 nameof
操作符:
@using ViewComponentSample.Models
@using ViewComponentSample.ViewComponents
@model IEnumerable<TodoItem>
<h2>ToDo nameof</h2>
<!-- Markup removed for brevity. -->
}
</table>
<div>
@await Component.InvokeAsync(nameof(PriorityList), new { maxPriority = 4, isDone = true })
</div>
附加的资源
ASP.NET Core 中文文档 第四章 MVC(3.9)视图组件的更多相关文章
- ASP.NET Core 中文文档 第四章 MVC(01)ASP.NET Core MVC 概览
原文:Overview of ASP.NET Core MVC 作者:Steve Smith 翻译:张海龙(jiechen) 校对:高嵩 ASP.NET Core MVC 是使用模型-视图-控制器(M ...
- ASP.NET Core 中文文档 第四章 MVC(4.2)控制器操作的路由
原文:Routing to Controller Actions 作者:Ryan Nowak.Rick Anderson 翻译:娄宇(Lyrics) 校对:何镇汐.姚阿勇(Dr.Yao) ASP.NE ...
- ASP.NET Core 中文文档 第四章 MVC(3.6.1 )Tag Helpers 介绍
原文:Introduction to Tag Helpers 作者:Rick Anderson 翻译:刘浩杨 校对:高嵩(Jack) 什么是 Tag Helpers? Tag Helpers 提供了什 ...
- ASP.NET Core 中文文档 第四章 MVC(3.8)视图中的依赖注入
原文:Dependency injection into views 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:孟帅洋(书缘) ASP.NET Core 支持在视图中使用 依赖 ...
- ASP.NET Core 中文文档 第四章 MVC(4.6)Areas(区域)
原文:Areas 作者:Dhananjay Kumar 和 Rick Anderson 翻译:耿晓亮(Blue) 校对:许登洋(Seay) Areas 是 ASP.NET MVC 用来将相关功能组织成 ...
- ASP.NET Core 中文文档 第四章 MVC(4.5)测试控制器逻辑
原文: Testing Controller Logic 作者: Steve Smith 翻译: 姚阿勇(Dr.Yao) 校对: 高嵩(Jack) ASP.NET MVC 应用程序的控制器应当小巧并专 ...
- ASP.NET Core 中文文档 第四章 MVC(4.4)依赖注入和控制器
原文: Dependency Injection and Controllers 作者: Steve Smith 翻译: 刘浩杨 校对: 孟帅洋(书缘) ASP.NET Core MVC 控制器应通过 ...
- ASP.NET Core 中文文档 第四章 MVC(4.1)Controllers, Actions 和 Action Results
原文:Controllers, Actions, and Action Results 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:许登洋(Seay) Action 和 acti ...
- ASP.NET Core 中文文档 第四章 MVC(3.7 )局部视图(partial)
原文:Partial Views 作者:Steve Smith 翻译:张海龙(jiechen).刘怡(AlexLEWIS) 校对:许登洋(Seay).何镇汐.魏美娟(初见) ASP.NET Core ...
随机推荐
- 【AR实验室】mulberryAR : ORBSLAM2+VVSION
本文转载请注明出处 —— polobymulberry-博客园 0x00 - 前言 mulberryAR是我业余时间弄的一个AR引擎,目前主要支持单目视觉SLAM+3D渲染,并且支持iOS端,但是该引 ...
- Fis3的前端工程化之路[三大特性篇之声明依赖]
Fis3版本:v3.4.22 Fis3的三大特性 资源定位:获取任何开发中所使用资源的线上路径 内容嵌入:把一个文件的内容(文本)或者base64编码(图片)嵌入到另一个文件中 依赖声明:在一个文本文 ...
- 【Machine Learning】KNN算法虹膜图片识别
K-近邻算法虹膜图片识别实战 作者:白宁超 2017年1月3日18:26:33 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结 ...
- ASP.NET Aries 入门开发教程7:DataGrid的行操作(主键操作区)
前言: 抓紧勤奋,再接再励,预计共10篇来结束这个系列. 上一篇介绍:ASP.NET Aries 入门开发教程6:列表数据表格的格式化处理及行内编辑 本篇介绍主键操作区相关内容. 1:什么时候有默认的 ...
- .Net中的AOP系列之构建一个汽车租赁应用
返回<.Net中的AOP>系列学习总目录 本篇目录 开始一个新项目 没有AOP的生活 变更的代价 使用AOP重构 本系列的源码本人已托管于Coding上:点击查看. 本系列的实验环境:VS ...
- JavaScript性能优化
如今主流浏览器都在比拼JavaScript引擎的执行速度,但最终都会达到一个理论极限,即无限接近编译后程序执行速度. 这种情况下决定程序速度的另一个重要因素就是代码本身. 在这里我们会分门别类的介绍J ...
- 一起学微软Power BI系列-使用技巧(3)Power BI安卓手机版安装与体验
Power BI有手机版,目前支持安卓,苹果和WP,不过没有WP手机,苹果在国内还不能用,要FQ和用就不测试了.安卓的我也也是费了九牛二虎之力才把app下载下来,把方法分享给大家. FQ太麻烦,所以建 ...
- C++随笔:.NET CoreCLR之GC探索(3)
有几天没写GC相关的文章了哈,今天我讲GC的方式是通过一个小的Sample来讲解,这个小的示例代码只有全部Build成功了才会有.地址为D:\coreclr2\coreclr\bin\obj\Wind ...
- UVA-146 ID Codes
It is 2084 and the year of Big Brother has finally arrived, albeit a century late. In order to exerc ...
- bzoj3037--贪心
题目大意: applepi手里有一本书<创世纪>,里面记录了这样一个故事--上帝手中有着N 种被称作"世界元素"的东西,现在他要把它们中的一部分投放到一个新的空间中去以 ...