参考文章地址:为什么要在 ASP.NET Core 中使用视图组件 (telerik.com)

为什么使用视图组件而不是分部视图?最大的原因是,在 Razor 页面中插入分部视图时,与调用 View 关联的所有 ViewData 都会自动与分部视图关联。这意味着分部视图在一个 Razor 页面上的行为可能与在另一个页面上的行为大不相同。使用 View Components,您可以控制共享到 View Components 的内容。

视图组件是 ASP.NET Core 的新功能,旨在执行 ASP.NET 以前版本中的分部视图所做的所有事情,甚至更多。视图组件是完全独立的对象,可始终如一地从 Razor 视图呈现 html。它们是从派生自基类 ViewComponent 的 C# 类生成的,通常与 Razor 文件相关联以生成标记。

因此,View 组件可以很好地分离和封装渲染输出所需的服务器端逻辑。就像 ASP.NET MVC 控制器一样,视图组件很容易测试,因为它们可以编写为没有副作用,这意味着更少的错误。

如果您想继续学习,本文中使用的所有源代码都托管在 GitHub 上,地址为:

https://github.com/pkellner/progress-telerik-blog-viewcomponent

从头开始创建视图组件

在本文中,我将使用 Visual Studio 2017 创建 ASP.NET Core 2.1 网站。我可以使用命令行工具 (dotnet) 在 Windows 或 Mac 上轻松创建应用,但我选择使用 Visual Studio。

第一步是创建一个新的 ASP.NET Core 2.1 网站。

对于 Web 应用程序的类型,我们将选择“Web 应用程序”,它将使用新的 ASP.NET Core Razor Pages 创建一个漂亮的简单网站。

为我们搭建的目录结构包含一个名为“Pages”的目录,在其中,我们将创建一个新文件夹,我们将在其中创建一个新的视图组件(这确实是本文的重点)。

在本文中,我们将开发一个非常有用的视图组件,可以在页面中反复使用该组件进行评级。由于视图组件通常同时具有 C# 文件和 Razor 视图页,因此让我们在组件目录中创建一个名为 RatingControl 的新目录,并在该目录中创建两个文件:RatingControlViewComponent.cs 和 Default.cshtml。

有几种方法可以基于属性和命名约定创建视图控件。在我们的例子中,我将显式创建我的,它派生自类 ViewComponent,它有一个空构造函数和一个只有一个参数的 Invoke 方法。与从控制器调用并将模型参数作为输入的典型 Razor 页面不同,View 组件是通过调用类方法 Invoke 或 InvokeAsync 直接调用的,并带有值。您可以将这些值视为模型。

下面是简单的视图组件,该组件在调用时仅传递单个参数 (ratingControlType),然后将该参数作为模型传递给 default.cshtml Razor 视图。

using Microsoft.AspNetCore.Mvc;

namespace WebApp.Pages.Components.RatingControl
{
public class RatingControlViewComponent : ViewComponent
{
public RatingControlViewComponent() { }
public IViewComponentResult Invoke(string ratingControlType)
{
return View("Default", ratingControlType);
}
}
}
C#

Razor View 文件 Default.cshtml 只有两行。第一行表示传入的模型类型只是一个字符串,第二行表示该字符串包装在 h2 中。

@model string
<h2>@Model</h2>
标记

在 Razor 页面上使用 Outlook 上的视图组件和 InvokeAsync

至此,我们有了一个完整的视图组件。要让该视图组件为我们做任何事情,我们可以将其放在 Razor 页面上。我创建了一个名为 RatingDemoInvokeAsync 的新 Razor 视图页,此处显示在解决方案资源管理器中。

文件本身使用 Component 方法 InvokeAsync,该方法引用 View Component 名称及其第一个参数,并且要将参数导入该方法,需要一个匿名类作为它的第二个参数。基本上,我们在这里只是使用 Razor 的功能。“@”符号将 Razor 视图页切换到 C#,然后接下来只是 C# 代码。下面是完整的 RatingDemoInvokeAsync.cshtml。

@page
@model WebApp.Pages.RatingDemoInvokeAsyncModel
@{
vLayout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>starsdemo1</title>
</head>
<body>
<h1>RatingDemoInvokeAsync</h1>
@await Component.InvokeAsync("RatingControl", new {
ratingControlType = "1to10"
})
</body>
</html>
标记

运行此页面的输出仅显示标题为 RatingDemoInvokeAsync 的字符串“1to10”。这是因为我们的 View 组件所做的只是渲染传递到其中的字符串。

在下一节中,我将介绍一种更简洁的方法来调用视图组件。也就是说,我们可以使用自己的自定义 HTML 元素(也称为标记帮助程序),而不是在 Razor 视图页中间使用 C#。

在带有标记帮助程序的 Razor 页面上使用视图组件

让我们首先看看使用标记帮助程序调用视图组件如何更改我们的 Razor 页面。在这里,我创建了一个新的 Razor 页面 RatingDemoTagHelper.cshtml。

@page
@model WebApp.Pages.RatingDemoTagHelperModel
@{
Layout = null;
}
@addTagHelper *, WebApp
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>RatingDemoTagHelper</title>
</head>
<body>
<h1>RatingDemoTagHelper</h1>
<vc:rating-control rating-control-type="1to10">
</vc:rating-control>
</body>
</html>
标记

我所做的只是添加了第 6 行,@addTagHelper它基本上说使用在我当前的 .NET 程序集中的任何位置定义的标记帮助程序。然后,我可以像在此 HTML 正文中一样引用评级控件,并使用 View 组件的标记帮助程序前缀 vc。这个名字只是我的视图组件名称,用烤肉串外壳拼写为评级控制。与其像上一节中的 invoke 方法那样使用丑陋的匿名类,不如将字符串传递给带有 HTML 属性的 View 组件,在 Kabob 的情况下也是如此,称为 rating-control-type。

这里的美妙之处在于,我们不必对视图组件进行任何修改即可使 Tag Helpers 工作。他们只是工作!运行页面当然会给我们提供与以前相同的输出,但我们已将 h1 内部 HTML 更改为 RatingDemoTagHelper。


ASP.NET 核心基础知识:标记帮助程序

在我们的基础知识系列中了解有关 ASP.NET 核心标记助手的更多信息。


让我们的评级视图组件栩栩如生

到目前为止,我们还没有创建评级视图组件。我们只创建了一个组件来渲染传递到其中的内容。不是很有用。然而,我们已经创建了基础,所以现在我们可以构建一个真实世界的有用控件。与其从头开始,不如使用这个使用 jQuery 和 Bootstrap 的出色 MIT 许可评级控件。

https://github.com/antennaio/jquery-bar-rating

我不会让你对细节感到厌烦,但我基本上已经将这个项目带到了我的 ASP.NET 核心 Visual Studio 项目中,将一些 CSS 和 JavaScript 复制到 Web 项目 wwwroot 的基础中,如下所示。

我创建了一个 Razor 视图页面,该页面只是从 jquery-bar-rating 存储库中的示例派生的静态 HTML。该文件是 Pages/RatingDemoRawHtml.cshtml,其中包含许多代码,如下所示:

运行该页面会显示支持的几种评级类型:

我们的目标是将 select 标签中的代码替换为 View 组件,该组件处理 HTML 选项的所有呈现,并处理必要的 JavaScript 和 jQuery。也就是说,完成后,我们将获得如下所示的 HTML(位于文件 pages/RatingDemoComplete.cshtml 中),而不是上面的原始 HTML 代码。

请注意,这显示了三种不同的评级类型:“1to10”、“movie”和“pill”。我还包含了一个我们以前从未见过的 rating-control-id-value 属性。通常,当我们实现评级控件时,我们希望我们的控件能够在用户单击或更改评级(通常是 Ajax 调用)时回发回服务器端端点以更新数据。此值实质上允许您将唯一标识符传递给控件(通常作为 Razor 变量传入)。例如,如果您正在循环访问会议会话,并且想知道哪个评级控制与哪个会话相关联,则可以使用 rating-control-id-value 来传递会话 ID。

当我们运行此页面 (Pages/RatingDemoComplete.cshtml) 时,我们会看到三种评级类型(在我的示例中,我只为这三种类型编写代码,尽管 github 基础项目 jquery-bar-rating 支持六种类型):

我们已经看到了呈现此内容的 Razor 页面,但这一切是从哪里来的?好吧,显而易见的答案是更新的视图组件。让我们看一下这段代码,并讨论它的作用。

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Configuration;
using System.Collections.Generic;
using System.Linq;
using WebApp.Models; namespace WebApp.Pages.Components.RatingControl
{
public class RingControlModel
{
public List<SelectListItem> SelectedListItems { get; set; }
public string RatingControlType { get; set; }
public string RatingControlValue { get; set; }
public int RatingControlIdValue { get; internal set; }
} public class RatingControlViewComponent : ViewComponent
{
private readonly RatingControlOptions _ratingControlOptions; public RatingControlViewComponent(IConfiguration config)
{
_ratingControlOptions = new RatingControlOptions
{
RatingControlType = config["RatingControlType"],
RatingControlInitialValue1to10 = config["RatingControlInitialValue1to10"],
RatingControlInitialValuePill = config["RatingControlInitialValuePill"],
RatingControlInitialValueMovie = config["RatingControlInitialValueMovie"]
};
} public IViewComponentResult Invoke(string ratingControlType,int ratingControlIdValue)
{
var ratingControlValues = new List<string>();
var ratingControlInitialValue = ""; if (ratingControlType == "pill")
{
_ratingControlOptions.RatingControlValuesPill.ForEach(a => ratingControlValues.Add(a));
ratingControlInitialValue = _ratingControlOptions.RatingControlInitialValuePill;
}
else if (ratingControlType == "1to10")
{
_ratingControlOptions.RatingControlValues1to10.ForEach(a => ratingControlValues.Add(a));
ratingControlInitialValue = _ratingControlOptions.RatingControlInitialValue1to10;
}
else if (ratingControlType == "movie")
{
_ratingControlOptions.RatingControlValuesMovie.ForEach(a => ratingControlValues.Add(a));
ratingControlInitialValue = _ratingControlOptions.RatingControlInitialValueMovie;
} List<SelectListItem> ratings = ratingControlValues.Select(
myValue => new SelectListItem
{
Value = myValue,
Text = myValue,
Selected = myValue.Equals(ratingControlInitialValue)
}).ToList(); RingControlModel ringControlModel = new RingControlModel
{
SelectedListItems = ratings,
RatingControlType = ratingControlType,
RatingControlValue = ratingControlInitialValue,
RatingControlIdValue = ratingControlIdValue
}; return View(ringControlModel);
}
}
}
C#

首先请注意,我们已将程序配置信息注入到第 23 行的控件构造函数中。也就是说,我们从appsettings.json文件中提取设置数据。这样,我们就不必将代码显式添加到 invoke 方法来提取此数据。下面是我们的appsettings.json文件,它只是覆盖了默认控制类型以及所有三种评级类型的初始值。

{
"RatingControlType": "1to10", // Default Type
"RatingControlInitialValue1to10": "6",
"RatingControlInitialValueMovie": "Good",
"RatingControlInitialValuePill": "C",
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
JavaScript的

在我们的 Invoke 方法中,从第 34 行开始,我们只需根据配置数据为 select 标记创建选项。我不会在这里详细介绍,因为它对于理解 View 组件并不那么重要,但请随时自行查看 GitHub 中的代码(本文顶部提到的存储库包括所有工作代码)。

最后一部分是 Pages/Components/RatingControl/Default.cshtml,如下所示:

@model RingControlModel
@{
var uniqueId = Guid.NewGuid().ToString("N");
}
<select id="@uniqueId"
asp-for="@Model.RatingControlValue"
asp-items="@Model.SelectedListItems"
rating-control-id-value=@Model.RatingControlIdValue></select>
<script>
$(document).ready(function () {
$('#@uniqueId').barrating('show', {
theme: 'bars-@Model.RatingControlType',
onSelect: function(value) {
alert('Selected rating: ' + value + ' id-value: ' + @Model.RatingControlIdValue);
}
});
});
</script>
标记

此组件视图 Razor 页首先创建一个唯一 ID,以分配给评级控件。然后,它继续执行与基本 jquery-bar-rating 存储库相同的 jQuery,该存储库用于设置标准 html select 元素的样式和添加功能。您可以看到第 13 行的 jQuery 在 select 控件上执行方法“barrating()”。该方法调用样式并添加必要的事件处理,以便我们的组件视图既美观又正常工作。

我意识到我遗漏了很多关于jquery-bar-rating代码如何工作的细节。本文的真正内容是关于视图组件的工作原理以及如何将它们构建到代码中。这个条形码评级只是一个很好的工作示例,您可以自己学习。它展示了一个真实的示例,您可以根据该示例对代码进行建模,而不仅仅是一个简单的“hello world”示例,该示例通常很难扩展。

如果您有问题,请随时在下面发表评论或提出问题。我喜欢 ASP.NET Core 的新功能。View Components 和 Tag Helpers 只是使我们作为 Web 开发人员的生活变得更加轻松的两个新功能。

您可以在此处了解有关如何在 ASP.NET 项目中使用 Tag Helpers 的更多信息,如果您正在寻找一组 UI 组件来帮助您构建 ASP.NET Core 应用程序,请不要忘记查看 Telerik UI for ASP.NET Core,它支持各种 TagHelpers。您可以立即开始免费试用 30 天

ASP.NET Core Razor Pages 使用 视图(View) 组件的更多相关文章

  1. ASP.NET Core Razor Pages

    Razor 页面是Asp.Net Core2.0新增的一个功能.Razor 页面是 ASP.NET Core MVC 的一个新特性,它可以使基于页面的编码方式更简单高效. 环境:vs2017 .net ...

  2. ASP.NET Core Razor Pages 初探

    最近新建 Asp.net Core MVC 项目的时候不小心选错了个模板,发现了一种新的项目模板.它使用cshtml视图模板,但是没有Controller文件夹.后来才发现这是ASP.NET Core ...

  3. ASP.NET Core - Razor页面之Handlers处理方法

    简介 在前一篇文章中,我们讨论了Razor页面.今天我们来谈谈处理方法(Handlers). 我们知道可以将代码和模型放在 .cshtml 文件里面或与 .cshtml 匹配的 .cshtml.cs ...

  4. ASP.NET Core:Pages

    ylbtech-ASP.NET Core:Pages 1.返回顶部 1._Layout.cshtm <!DOCTYPE html> <html> <head> &l ...

  5. .NET Core Razor Pages中ajax get和post的使用

    ASP.NET Core Razor Pages Web项目大部分情况下使用继承与PageModel中的方法直接调用就可以(asp-page),但是有些时候需要使用ajax调用,更方便些.那么如何使用 ...

  6. 007.Adding a view to an ASP.NET Core MVC app -- 【在asp.net core mvc中添加视图】

    Adding a view to an ASP.NET Core MVC app 在asp.net core mvc中添加视图 2017-3-4 7 分钟阅读时长 本文内容 1.Changing vi ...

  7. ASP.NET Core Razor 视图组件

    视图组件简介 在新的ASP.NET Core MVC中,视图组件类似于局部视图,但它们更强大.视图组件不使用模型绑定,仅依赖于您在调用时提供的数据. 视图组件特性: 呈现页面响应的某一部分而不是整个响 ...

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

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

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

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

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

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

随机推荐

  1. 【Ubuntu】在Ubuntu上安装IDEA

    [Ubuntu]在Ubuntu上安装IDEA 零.前言 最近换了Ubuntu系统,但是还得是要写代码,这样就不可避免地用到IDEA,接下来介绍一下如何在Ubuntu上安装IDEA. 壹.下载 这一步应 ...

  2. P3392 涂国旗 题解

    题目大意 题目真的是不说人话...... 有一个国家的国旗是由一个 N * M 的方格组成的.如果想要这面国旗合法,就必须满足要求: 国旗从上到下必须是白色.蓝色和红色,顺序不能改变. 每一种颜色都至 ...

  3. Armbian安装防火墙软件

    在Armbian操作系统中安装防火墙是一项提升系统安全性的重要步骤.Armbian是一个针对ARM架构设备的Debian Linux发行版,它广泛应用于各类ARM开发板和单板计算机上.下面将具体展开讲 ...

  4. 静态批处理/动态批处理/GPU Instancing /SRP Batcher的详细剖析

    静态批处理[1] 定义 标明为 Static 的静态物件,如果在使用相同材质球的条件下,在Build(项目打包)的时候Unity会自动地提取这些共享材质的静态模型的Vertex buffer和Inde ...

  5. 如何在 MySQL 中监控和优化慢 SQL?

    如何在 MySQL 中监控和优化慢 SQL? 在 MySQL 中,慢 SQL 查询是指那些执行时间较长的查询,通常会影响数据库的性能和响应时间.通过监控和优化这些慢 SQL 查询,可以提高数据库的效率 ...

  6. MySQL 中使用索引一定有效吗?如何排查索引效果?

    MySQL 中使用索引一定有效吗?如何排查索引效果? 虽然索引是提升 MySQL 查询性能的常见手段,但并不是所有情况下索引都会有效.索引的使用取决于查询条件.数据分布.索引设计等多个因素.如果索引未 ...

  7. matlab 实现傅里叶变换

    实现傅里叶变换: ag = im2single(a1); a = fftshift(fft2(ag));%傅里叶变换和移位 aa = real(ifft2(ifftshift(csf.*a)));

  8. JS 原型链查找

    我们都知道面向对象语言如 Java, C++ 等都基本实现了 封装, 继承, 多态 等特性, 用面向对象语言来编程的基本套路就是抽象出类, 然后实例化, 用实例调用方法来模拟进行程序间的通信. 但 J ...

  9. .NET外挂系列:7. harmony在高级调试中的一些实战案例

    一:背景 1. 讲故事 如果你读完前六篇,我相信你对 harmony 的简单使用应该是没什么问题了,现在你处于手拿锤子看谁都是钉子的情况,那这篇我就找高级调试里非常经典的 3个钉子 让大家捶一锤. 二 ...

  10. LocalSend 编译全过程深度讲解,解决手机与电脑互传文件痛点

    localsend编译 LocalSend 是一款开源.跨平台的 本地网络文件传输工具,旨在通过局域网实现设备间快速.安全的文件共享,无需依赖互联网或第三方服务器.它支持 Windows.macOS. ...