在新的ASP.NET Core MVC中,视图组件类似于局部视图,但它们更强大。视图组件不使用模型绑定,仅依赖于您在调用时提供的数据。
视图组件特性:
视图组件是在任何地方可重用的呈现逻辑,对于局部视图来说相对复杂,例如:
视图组件由两部分组成:类(通常继承自ViewComponent)和返回的结果(通常是视图)。像控制器一样,视图组件可以是POCO,但大多数开发人员都希望利用从
继承的方法和属性。
- ViewComponent
此部分包含创建视图组件的高级功能。在本文的后面,我们将详细介绍每一个步骤,并创建一个视图组件。
视图组件类可以通过以下任何方式来创建:
特性来标记一个类,或者继承自具有
- [ViewComponent]
特性的类
- [ViewComponent]
与控制器一样,视图组件必须是公共、非嵌套、非抽象类。视图组件名称是删除“ViewComponent”后缀的类名称,也可以使用
属性显式指定名称。
- ViewComponentAttribute.Name
视图组件类特性:
视图组件在
方法中定义逻辑,并返回
- InvokeAsync
类型。参数直接来自视图组件的调用,而不是模型绑定;视图组件从不直接处理请求;通常视图组件会初始化模型,并通过调用
- IViewComponentResult
方法将其传递给视图。总而言之,视图组件方法特性:
- View
的
- IViewComponentResult
方法
- InvokeAsync
类型的
- ViewComponent
方法将其传递给视图
- View
运行时在以下路径中搜索视图:
视图组件的视图名称默认为Default,这意味着您的视图文件通常将命名为Default.cshtml。创建视图组件结果或调用
方法时,可以指定不同的视图名称。
- View
我们建议您视图文件命名为Default.cshtml,并使用Views/Shared/Components/
视图组件,视图的路径是Views/Shared/Components/PriorityList/Default.cshtml。
- PriorityList
要使用视图组件,请在视图中调用以下代码:
- @Component.InvokeAsync("Name of view component", <anonymous type containing parameters > )
参数将被传递给
方法,在本文中编写的
- InvokeAsync
视图组件在Views/Todo/Index.cshtml视图文件中调用。在下文中,使用两个参数调用
- PriorityList
方法:
- InvokeAsync
- @await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
对于ASP.NET Core 1.1及更高版本,您可以将视图组件作为标签帮助器(Tag Helper)进行调用:
- <vc:priority-list max-priority="2" is-done="false">
- </vc:priority-list>
标签帮助器将Pascal命名方式的类型和方法参数被转换成它们的小写短横线命名方式(lower kebab case)。调用视图组件的标签帮助器使用该
- <vc:[view-component-name]
- parameter1="parameter1 value"
- parameter2="parameter2 value">
- </vc:[view-component-name]>
注意:为了将视图组件作为标签帮助器,您必须使用
指令注册包含视图组件的程序集。例如,如果您的视图组件位于名为“MywebApp”的程序集中,请将以下指令添加到
- @addTagHelper
文件中:
- _ViewImports.cshtml
- @addTagHelper *, MyWebApp
您可以将视图组件作为标签帮助器注册到引用视图组件的任何文件。有关如何注册标签助手的更多信息,请参阅Managing Tag Helper Scope。
本示例中使用的
方法:
- InvokeAsync
- @await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
标签帮助器标记:
- <vc:priority-list max-priority="2" is-done="false">
- </vc:priority-list>
在上面的示例中,
视图组件变为
- PriorityList
;视图组件的参数作为属性按小写短横线命名方式传递。
- priority-list
视图组件通常在视图调用,但您也可以直接在控制器的方法中调用它们。虽然视图组件被定义为不能像控制器一样直接处理请求,但您可以轻松在控制器的Action方法中实现返回
内容。
- ViewComponentResult
在下面的示例中,在控制器直接调用视图组件:
- public IActionResult IndexVC()
- {
- return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
- }
示例下载,构建和测试入门代码。这是一个简单的项目,
控制器显示 Todo 项目列表。
- Todo
创建一个 ViewComponents 文件夹并添加以下
类:
- PriorityListViewComponent
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.EntityFrameworkCore;
- 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();
- }
- }
- }
代码注意事项:
特性可以更改用于引用视图组件的名称。例如,我们可以该类命名为
- [ViewComponent]
并应用该
- XYZ
属性:
- ViewComponent
- [ViewComponent(Name = "PriorityList")]
- public class XYZ : ViewComponent
特性告诉视图组件选择器在查找与组件关联的视图时使用名称
- [ViewComponent]
,并在从视图引用组件类时使用字符串“PriorityList”。稍后我会详细解释一下。
- PriorityList
可用。
- DbContext
是一个可以从视图中调用的公开方法,它可以使用任意数量的参数。
- InvokeAsync
方法返回满足
- InvokeAsync
和
- isDone
参数的
- maxPriority
集合。
- ToDo
文件夹,此文件夹必须命名为Components。
- Views/Shared/Components
后缀)。如果您使用该
- ViewComponent
特性,则名称需要与特性名称一致。
- ViewComponent
- @model IEnumerable<ViewComponentSample.Models.TodoItem>
- <h3>Priority Items</h3>
- <ul>
- @foreach (var todo in Model)
- {
- <li>@todo.Name</li>
- }
- </ul>
并显示它们。如果视图组件
- TodoItem
方法未传递视图的名称(如我们的示例中),则按照约定视图名称为Default。在本文的后面,我将向您展示如何传递视图的名称。如果视图组件只适用于特定控制器,则可以将其添加到控制器特定的文件夹(Views/Todo/Components/PriorityList/Default.cshtml)。
- InvokeAsync
元素中包含视图组件的调用
- div
- <div >
- @await Component.InvokeAsync("PriorityList", new { maxPriority = 2, isDone = false })
- </div>
是调用视图组件的语法。第一个参数是我们要调用组件的名称,随后是传递给组件的参数。
- @await Component.InvokeAsync
可以包含任意数量的参数。
- InvokeAsync
调试应用程序,下图显示了ToDo列表和选择项:
您也可以直接在控制器中调用视图组件:
- public IActionResult IndexVC()
- {
- return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
- }
复杂视图组件可能需要在某些情况下指定非默认视图。以下代码显示了如何从
方法中指定“PVC”视图。修改
- InvokeAsync
类中的
- 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:
- @await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
运行应用程序并验证是PVC视图。
如果显示不是PVC视图,请验证您调用视图组件
参数是否为4或更高的。
- priority
参数更改为三个或更小,返回默认视图。
- priority
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
EnsureSuccessful
如果要编译时安全,则可以使用类名替换硬编码视图组件名称。创建没有以“ViewComponent”后缀的视图组件:
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.EntityFrameworkCore;
- 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();
- }
- }
- }
使用
将命名空间添加到您的Razor视图文件,并使用
- using
运算符:
- nameof
- @using ViewComponentSample.Models
- @using ViewComponentSample.ViewComponents
- @model IEnumerable<TodoItem>
- <h2>ToDo nameof</h2>
- <div>
- @await Component.InvokeAsync(nameof(PriorityList), new { maxPriority = 4, isDone = true })
- </div>
来源: http://www.cnblogs.com/tdfblog/p/view-components-in-asp-net-core.html