视图组件简介

在新的ASP.NET Core MVC中,视图组件类似于局部视图,但它们更强大。视图组件不使用模型绑定,仅依赖于您在调用时提供的数据。

视图组件特性:

  • 呈现页面响应的某一部分而不是整个响应
  • 包括在控制器和视图之间发现的关注分离和可测试性优势
  • 可以具有参数和业务逻辑
  • 通常在页面布局中调用

视图组件是在任何地方可重用的呈现逻辑,对于局部视图来说相对复杂,例如:

  • 动态导航菜单
  • 标签云(查询数据库)
  • 登录面板
  • 购物车
  • 最近发表的文章
  • 典型博客上的侧边栏内容
  • 将在每个页面上呈现的登录面板,并显示要注销或登录的链接,具体取决于用户的登录状态

视图组件由两部分组成:类(通常继承自ViewComponent)和返回的结果(通常是视图)。像控制器一样,视图组件可以是POCO,但大多数开发人员都希望利用从ViewComponent继承的方法和属性。

创建视图组件

此部分包含创建视图组件的高级功能。在本文的后面,我们将详细介绍每一个步骤,并创建一个视图组件。

视图组件类

视图组件类可以通过以下任何方式来创建:

  • 继承自 ViewComponent
  • 使用[ViewComponent]特性来标记一个类,或者继承自具有[ViewComponent]特性的类
  • 创建类的名称以 ViewComponent 后缀结尾

与控制器一样,视图组件必须是公共、非嵌套、非抽象类。视图组件名称是删除“ViewComponent”后缀的类名称,也可以使用ViewComponentAttribute.Name属性显式指定名称。

视图组件类特性:

  • 完美支持构造函数依赖注入
  • 不参与控制器生命周期,这意味着您不能在视图组件中使用过滤器

视图组件方法

视图组件在InvokeAsync方法中定义逻辑,并返回IViewComponentResult类型。参数直接来自视图组件的调用,而不是模型绑定;视图组件从不直接处理请求;通常视图组件会初始化模型,并通过调用View方法将其传递给视图。总而言之,视图组件方法特性:

  • 定义一个返回IViewComponentResultInvokeAsync方法
  • 通常会初始化一个模型,并通过调用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>.cshtml路径。此示例中使用的PriorityList视图组件,视图的路径是Views/Shared/Components/PriorityList/Default.cshtml

调用视图组件

要使用视图组件,请在视图中调用以下代码:

    @Component.InvokeAsync("Name of view component", <anonymous type containing parameters>)

参数将被传递给InvokeAsync方法,在本文中编写的PriorityList视图组件在Views/Todo/Index.cshtml视图文件中调用。在下文中,使用两个参数调用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]>

注意:为了将视图组件作为标签帮助器,您必须使用@addTagHelper指令注册包含视图组件的程序集。例如,如果您的视图组件位于名为“MyWebApp”的程序集中,请将以下指令添加到_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 项目列表。

添加ViewComponent类

创建一个 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();
} }
}

代码注意事项:

  • 视图组件类可以包含在项目中的任何文件夹中。
  • 因为类名称PriorityListViewComponent以后缀ViewComponent结尾,运行时在视图中引用视图组件时使用字符串“PriorityList”。稍后我会详细解释一下。
  • [ViewComponent]特性可以更改用于引用视图组件的名称。例如,我们可以该类命名为XYZ并应用该ViewComponent属性:
        [ViewComponent(Name = "PriorityList")]
    public class XYZ : ViewComponent
  • [ViewComponent]特性告诉视图组件选择器在查找与组件关联的视图时使用名称PriorityList,并在从视图引用组件类时使用字符串“PriorityList”。稍后我会详细解释一下。
  • 组件使用依赖注入来使DbContext可用。
  • InvokeAsync 是一个可以从视图中调用的公开方法,它可以使用任意数量的参数。
  • InvokeAsync方法返回满足isDonemaxPriority参数的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/index.cshtml 文件底部的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 });
}

指定视图名称

复杂视图组件可能需要在某些情况下指定非默认视图。以下代码显示了如何从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

    @await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })

运行应用程序并验证是PVC视图。

如果显示不是PVC视图,请验证您调用视图组件priority参数是否为4或更高的。

检测视图路径

  • priority参数更改为三个或更小,返回默认视图。
  • 临时将 Views/Todo/Components/PriorityList/Default.cshtml 重命名为 1Default.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

    EnsureSuccessful

  • 将视图 Views/Todo/Components/PriorityList/1Default.cshtml 复制到 Views/Shared/Components/PriorityList/Default.cshtml
  • Shared 的Todo视图组件视图中添加一些标记,以表示视图来自 Shared 文件夹。
  • 测试 Shared 组件视图。

避免字符串魔法

如果要编译时安全,则可以使用类名替换硬编码视图组件名称。创建没有以“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();
}
}
}

使用using将命名空间添加到您的Razor视图文件,并使用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>

其它资源

原文:《View components》https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components

翻译:Sweet Tang

本文地址:http://www.cnblogs.com/tdfblog/p/view-components-in-asp-net-core.html

欢迎转载,请在明显位置给出出处及链接。

ASP.NET Core Razor 视图组件的更多相关文章

  1. ASP.NET Core Razor 视图导入 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core Razor 视图导入 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core Razor 视图导入 上一章节我们介绍了视图起始页,学习 ...

  2. ASP.NET Core Razor 视图起始页 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core Razor 视图起始页 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core Razor 视图起始页 上一章节中我们介绍了布局视图, ...

  3. ASP.NET CORE 自定义视图组件(ViewComponent)注意事项

    *红色字体为固定命名,蓝色为一般命名规则,黄色为ASP.NET CORE 默认查找文件名 概要:1.简单ViewComponent的用法 2.ViewComponent控制器返回值  3.注意事项 1 ...

  4. ASP.NET Core Razor 视图预编译、动态编译

    0x01 前言 ASP.NET Core在默认发布情况下,会启动预编译将试图编译成xx.Views.dll,也许在视图中打算修改一处很细小的地方我们需要再重新编译视图进行发布.下面我将从 ASP.NE ...

  5. ASP.NET Core Razor 布局视图 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core Razor 布局视图 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core Razor 布局视图 上一章节中我们学习了如何使用 EF ...

  6. ASP.NET Core - Razor 页面简介

    简介 随着ASP.NET Core 2 即将来临,最热门的新事物是Razor页面.在之前的一篇文章中,我们简要介绍了ASP.NET Core Razor 页面. Razor页面是ASP.NET Cor ...

  7. ASP.NET Core Razor 页面使用指南

    ASP.NET Core Razor 页面作为 ASP.NET Core 2.0的一部分发布,它是基于页面的全新的Web开发框架.如果您想学习如何使用 ASP.NET Core Razor 页面,可以 ...

  8. 学习ASP.NET Core Razor 编程系列十九——分页

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  9. ASP.NET Core - Razor 页面介绍

    简介 随着ASP.NET Core 2 即将来临,最热门的新事物是Razor页面.在之前的一篇文章中,我们简要介绍了ASP.NET Core Razor 页面. Razor页面是ASP.NET Cor ...

随机推荐

  1. 配置SSH隧道访问Ubuntu服务器上的MongoDB

    为了数据安全,在MongoDB的配置文件里,一般会把默认的27017端口port改为自定义的端口号,然后把允许访问的IP设为127.0.0.1(即主机本身).但是这样就会在开发的过程查看数据时带来麻烦 ...

  2. javascript基础知识3#引用类

    引用类 引用类型的只是引用类型的一个实例,在ecmascript当中,引用类型是一种数据结构用于将数据和功能组织在一起,也常被称做类. object类型 构造函数[var o = new object ...

  3. spring集成mybatis实现mysql读写分离

    前言 在网站的用户达到一定规模后,数据库因为负载压力过高而成为网站的瓶颈.幸运的是目前大部分的主流数据库都提供主从热备功能,通过配置两台数据库主从关系,可以将一台数据库的数据更新同步到另一台服务器上. ...

  4. NYOJ--114--某种序列(大数)

    某种序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 数列A满足An = An-1 + An-2 + An-3, n >= 3 编写程序,给定A0, A1 ...

  5. Python数据可视化Matplotlib——Figure画布背景设置

    之前在今日头条中更新了几期的Matplotlib教学短视频,在圈内受到了广泛好评,现应大家要求,将视频中的代码贴出来,方便大家学习. 为了使实例图像显得不单调,我们先将绘图代码贴上来,此处代码对Fig ...

  6. h5 录音

    得益于前辈的分享,做了一个h5录音的demo.效果图如下: 点击开始录音会先弹出确认框: 首次确认允许后,再次录音不需要再确认,但如果用户点击禁止,则无法录音: 点击发送 将录音内容发送到对话框中.点 ...

  7. JavaScript闭包只学这篇就够了

    闭包不是魔法 这篇文章使用一些简单的代码例子来解释JavaScript闭包的概念,即使新手也可以轻松参透闭包的含义. 其实只要理解了核心概念,闭包并不是那么的难于理解.但是,网上充斥了太多学术性的文章 ...

  8. Maven注意事项

    Maven好处: 1.依赖管理:对jar包统一管理 2.项目构建:项目编码完成后,对项目进行编译.测试.打包.部署,实现项目一键发布1.配置环境变量    注意:maven工具必须有jdk环境.并且: ...

  9. mac系统读写NTFS格式的移动硬盘

    Mac OS X默认情况下,对于NTFS的移动硬盘只能读不能写,可通过将移动硬盘格式化为exFAT 或者安装NTFS相关的工具,达到可读写的目的,但对于系统的安全性方面,以上方式得不到保证:在Mac ...

  10. kali linux 2.0下搭建DVWA渗透测试演练平台

    DVWA (Dam Vulnerable Web Application)DVWA是用PHP+MySQL编写的一套用于常规WEB漏洞教学和检测的WEB脆弱性测试程序.包含了SQL注入.XSS.盲注等常 ...