65.9K
CodeProject 正在变化。 阅读更多。
Home

迁移到 ASP.NET Core Tag Helpers

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2018年3月14日

CPOL

9分钟阅读

viewsIcon

20296

在本文中,我们将学习如何将现有的 HTML Helper 模式迁移到 Tag Helpers。通过这个过程,我们将为在 ASP.NET Core 项目中使用 Tag Helpers 形成一个坚实的参考。

简介

当 ASP.NET Core 发布时,Tag Helpers 被引入——一种用于封装 HTML 标记的新功能。向框架添加 Tag Helpers 的目的是在开发者使用服务器渲染的标记片段时,提供类似 HTML 的体验。这里的想法不是替换 HTML Helpers,而是提供另一种方法,它通过使用标签属性来遵循与 HTML 相同的约定。

经验丰富的 ASP.NET 开发者可能会发现 Tag Helpers 需要一些时间来适应。编写 Tag Helper 的语法更简洁,不像传统的 Razor 那样需要特殊的 @ 转义字符。虽然 Tag Helpers 需要更少的上下文切换,但乍一看可能感觉像一个黑盒子。为了克服 Tag Helpers 的学习曲线,我们将了解一些基本概念。利用这些知识,我们将学习如何将现有的 HTML Helper 模式迁移到 Tag Helpers。通过这个过程,我们将为在 ASP.NET Core 项目中使用 Tag Helpers 形成一个坚实的参考。

入门

在我们开始使用 Tag Helpers 之前,确保我们的项目已配置为使用 Tag Helpers 非常重要。至少,我们需要使用 ASP.NET Core 项目。Tag Helpers 在 ASP.NET 4.x MVC 项目中不可用。

在我们的 ASP.NET Core 项目中,我们需要确保 Tag Helpers 已启用。这包括我们想要使用的任何第三方 Tag Helper 库。要为我们的项目声明 Tag Helpers,我们将在 *_ViewImports.cshtml* 文件中使用 @addTagHelper 指令。在此文件内,声明了应用程序视图作用域中所有可用的命名空间。在下面的示例中,我们同时拥有 ASP.NET Core 原生 Tag Helpers 以及来自 Telerik UI for ASP.NET Core 包的其他 UI 组件。

@* Default ASP.NET Core Tag Helpers *@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@* Telerik UI For ASP.NET Core Tag Helpers *@
@addTagHelper *, Kendo.Mvc

让我们快速测试一下,以确保我们的 Tag Helpers 能够正常工作,方法是编写我们的第一个 Tag Helper。我们将使用 /Home/Index.cshtml 视图作为工作区来开始编写我们的标记。在视图中,添加一个 Tag Helper 来创建一个简单的链接。为此,我们将编写 <a asp-action="Index">Home</a>。如果一切配置正确,代码将以粗体显示。

现在我们已经编写了第一个 Tag Helper,让我们用它来识别一些常见的模式,这些模式在发现新 Tag Helpers 和学习如何从 HTML Helper 语法转换为 Tag Helpers 时会很有帮助。

我们将继续以 Anchor Tag Helper 为例。让我们看看标记的一些特征,以识别 Tag Helpers 使用的常见模式。通过理解这些模式,我们可以通过 IntelliSense 更容易地发现 Tag Helpers。我们还将了解某些参数已移至何处。

Tag Helper 属性

如果我们比较 Anchor Tag Helper 和等效的 HTML Helper,我们可以识别出关键区别。在下面的示例中,命名参数用于 HTML Helper,以帮助识别值映射到等效 Tag Helper 的位置。正如我们所见,此版本使用Tag Helper 属性结合 HTML <a> 锚标记来识别操作名称。链接文本仅遵循锚标记的常规 HTML 约定。

<a asp-action="Index">Home</a>
@Html.ActionLink(linkText: "Home", actionName: "Index")

Tag Helper 属性需要更少的 HTML 抽象,从而减少了标记的视觉干扰。当我们开始向元素添加标准 HTML 属性时,我们可以看到 HTML 和 Tag Helpers 的更多融合。

标准属性

要使用 HTML Helpers 向标记添加标准 HTML 属性,我们将使用 htmlAttributes 参数并传入一个匿名对象。由于参数被编写为匿名 C# 对象,因此它必须遵循 C# 规则,并且仅应用 C# IntelliSense。这意味着我们必须转义 C# 关键字,并且 CSS 或 HTML 没有 IntelliSense。

@Html.ActionLink("Home", "Index", new { @class="btn btn-primary", role="button" })

当我们使用 Tag Helper 编写相同的标准属性时,这些属性被视为 HTML。由于上下文没有更改为 C#,因此我们不再需要转义关键字。我们继续获得正确的 IntelliSense。

<a asp-action="Index" class="btn btn-primary" role="button">Home</a>

正如标准属性被视为普通 HTML 一样,Tag Helper 的内部内容也是如此。操作名称 Home,只是写在标签内的内容。

标签和内容

正如我们在上一个示例中看到的,在 Tag Helper 中设置操作名称非常轻松。由于 Tag Helpers 遵循 HTML 的自然流程,因此使用 Tag Helpers 表示容器 UI 元素比使用 HTML Helpers 更容易。HTML <form> 是 HTML Helpers 如何使事情变得困难的一个主要示例。由于 HTML Helpers 没有开始/结束概念,它们通常依赖 @using 语句作为内容容器的代理。

@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal"}))
{
    <!-- Form Content -->
}

我们可以使用 Form Tag Helper 重写相同的标记。Form Tag Helper 和 BeginForm HTML Helper 在功能上是相似的。它们都为 MVC 控制器操作或命名路由生成 HTML <form> 元素和 action 属性值。此外,还会渲染一个隐藏的请求验证令牌,以防止跨站点请求伪造(当与 HTTP Post 操作方法中的 [ValidateAntiForgeryToken] 属性一起使用时)。

Form Tag Helper 提高了可读性,因为它不需要 using 语句、{} 大括号或 @ 转义字符。

@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal"}))
{
    <!-- Form Content -->
}

<form asp-action="Register" asp-controller="Account" method="post" class="form-horizontal">
    <!-- Form Content -->
</form>

表单的内容可以是任何 HTML、HTML Helper 或 Tag Helper。将表单迁移为仅使用标准 HTML 和 Tag Helpers 的影响减少了标记的整体视觉干扰。

Tag Helpers 自然地流入 HTML 结构中作为内容容器。作为自然内容容器,Tag Helpers 拥有另一项使它们区别于 HTML Helpers 的功能——子 Tag Helper。

子 Tag Helper

子 Tag Helpers 允许通过使用父子关系来组合复杂的 UI 元素。子 Tag Helpers 特定于父级,并且仅在父元素上下文中可用。考虑一个复杂的 UI 组件,例如 Telerik UI for ASP.NET Core Kendo UI 网格,它具有许多可配置元素。这些元素包括数据源、列、行、模板和编辑模式。此外,数据网格还具有用于启用排序、过滤和分页等功能的属性。可以通过流利的 HTML Helper 或可链接的 API 集合来创建网格,这些 API 集合会渲染 HTML。

使用网格 HTML Helper,通过 API 链配置网格的各个方面。链以设置 Name 属性开始。然后我们构建 Columns 配置,启用功能,并配置 DataSource。

得益于流畅的 API 链和 IntelliSense,设置网格及其所有各个部分是一个简化的过程。

@(Html.Kendo().Grid<CustomerViewModel>()
      .Name("grid")
      .Columns(columns =>
      {
          columns.Bound(c => c.ContactName).Title("Contact Name").Width(240).Filterable(ftb => ftb.Multi(true));
          columns.Bound(c => c.ContactTitle).Title("Contact Title");
          columns.Bound(c => c.CompanyName).Title("Company Name");
          columns.Bound(c => c.Country).Title("Country").Width(150);
      })
      .Groupable()
      .Sortable()
      .Filterable()
      .Pageable(pageable => pageable
          .Refresh(true)
          .PageSizes(new int[] { 5, 10, 20 })
          .ButtonCount(5))
      .DataSource(dataSource => dataSource
          .Ajax()
          .Read(read => read.Action("Orders_Read", "Grid"))
          .PageSize(20)
      )
)

使用 Tag Helpers,我们可以使用子 Tag Helpers 获得类似的体验。与其开始调用 API 链,不如打开一个新的 <kendo-grid> 标签,并在网格的 `body` 中开始一个新的标签。

列、功能和 DataSource 配置都在 `body` 中使用子 Tag Helpers 指定。子 Tag Helper 模式一直持续到设置完所有所需的选项并完全配置好网格。

<kendo-grid name="grid">
    <columns>
        <column field="@nameof(CustomerViewModel.ContactName)" title="Contact Name" width="240">
            <filterable multi="true"></filterable>
        </column>
        <column field="@nameof(CustomerViewModel.ContactTitle)" title="Contact Title" />
        <column field="@nameof(CustomerViewModel.CompanyName)" title="Company Name" />
        <column field="@nameof(CustomerViewModel.Country)" title="Country" width="150" />
    </columns>
    <groupable enabled="true" />
    <sortable enabled="true" />
    <filterable enabled="true" />
    <pageable button-count="5" refresh="true" page-sizes="new int[] { 5, 10, 20 }">
    </pageable>
    <datasource type="DataSourceTagHelperType.Ajax">
        <transport>
            <read url="@Url.Action("Orders_Read", "Grid")" />
        </transport>
    </datasource>
</kendo-grid>

子 Tag Helpers 提供了一种编写复杂 UI 元素的结构化方法,同时保持类似 HTML 的文档流。

仔细查看上面的代码,注意属性与使用 HTML Helpers 的版本是相同的。在属性完成方式上存在一些细微的差异,例如列字段名称。为简单起见,列子 Tag Helper 使用字符串值的 field 属性,而 HTML Helper 使用模型表达式。

通过利用 Razor 和 nameof 运算符,基于字符串的 field 属性可以轻松执行等效任务。

field="@nameof(CustomerViewModel.ContactName)"

由于 Tag Helpers 是 Razor 标记,因此它们可以轻松地从 HTML 过渡到 C#,或者在必要时与 HTML Helpers 结合使用。

组合 Helper

请记住,Tag Helpers 的目的不是替换 HTML Helpers,而是提供另一种编写标记的方法。HTML Helpers 继续在 ASP.NET Core 中工作,它们也可以与 Tag Helpers 结合使用。当 Tag Helper 不可用或它提供了更好的开发者体验时,混合使用 Tag Helpers 和 HTML Helpers 是可以接受的。同时使用两者也可以提供在迁移到 Tag Helpers 期间的临时解决方案或缓解学习过程。

Telerik UI for ASP.NET Core 的 Kendo UI 响应式面板 Tag Helper 类似于 Form Tag Helper,是一个内容容器。其主要目的是提供一个弹出式面板,用于显示标签 `body` 中包含的 HTML 内容。由于 `body` 部分是 Razor 标记,因此它可以包含 Tag Helpers、HTML Helpers、标准 HTML 或它们的任何组合。

在以下示例中,<kendo-responsivepanel> Tag Helper 与包含标准 HTML 标签和 DateInput HTML Helpers 的 `body` 一起使用。

<kendo-responsivepanel name="slidebar" breakpoint="1000" orientation="left">

    <label for="dateinput1">Begin Date</label>
    @(Html.Kendo().DateInput()
        .Name("dateinput1")
        .Format("MMMM yyyy")
        .Value(DateTime.Now)
    )

    <label for="dateinput2">End Date</label>
    @(Html.Kendo().DateInput()
            .Name("dateinput2")
            .Format("MMMM yyyy")
            .Value(DateTime.Now)
    )

</kendo-responsivepanel>

我们也可以使用标准 HTML 标签和 <kendo-dateinput> Tag Helpers 来表达 `body` 内容。这两个代码示例都会生成相同的 HTML 输出。

<kendo-responsivepanel name="slidebar" breakpoint="1000" orientation="left">

    <label for="dateinput1">Begin Date</label>
    <kendo-dateinput name="dateinput1" format="MMMM yyyy" value="DateTime.Now">
    </kendo-dateinput>

    <label for="dateinput2">End Date</label>
    <kendo-dateinput name="dateinput2" format="MMMM yyyy" value="DateTime.Now">
    </kendo-dateinput>

</kendo-responsivepanel>

开发者的首选示例基于对 HTML Helpers 或 Tag Helpers 的熟悉程度。虽然 Tag Helpers 提供了美学上的好处,或者减少了视觉干扰,但也有一些额外的优势。根据 Tag Helper 的源代码编写方式,可能可以获得更好的性能。Tag Helpers 可以被编写为利用 异步处理,或 ProcessAsync,就像 Telerik UI for ASP.NET Core Tag Helpers 的情况一样。由于底层代码使用了 ProcessAsync,<kendo-dateinput> Tag Helper 的渲染速度可能比其 HTML Helper 对应项更快。

结论

通过这些示例,我们探索了 ASP.NET Core Tag Helpers 使用的常见模式。Tag Helpers 通过使用标签属性来封装 HTML 标记,提供类似 HTML 的体验。通过使用 Tag Helper 的 `body` 部分,可以轻松添加子内容,而无需复杂的 @using 语句。Tag Helpers 通过利用 class 和 role 等标准 HTML 属性,减少了上下文切换,并且不需要转义字符。它们在 Razor 文档中产生的视觉干扰更少。

开发人员应该会发现从 HTML Helpers 迁移到 Tag Helpers 相对容易。虽然这两个概念的语法不同,但约定和工具可以帮助弥合差距。子 Tag Helpers 的引入通过为 Kendo UI 网格等复杂 UI 模式提供可发现性和 IntelliSense,从而改善了开发者体验。能够在同一个 Razor 文件中同时使用标准 HTML、HTML Helpers 和 Tag Helpers,可以减轻整体学习曲线。

虽然迁移到 Tag Helpers 仍然是可选的,并且由开发人员自行决定使用多少,但通过 Tag Helpers 用于渲染 HTML 的底层 ProcessAsync,有可能获得性能上的提升。

要尝试各种 Tag Helpers,包括网格、图表、图形和响应式面板等导航元素,请下载 Telerik UI for ASP.NET Core 的 30 天免费试用版。如果您已订阅 Telerik DevCraft 套件,则已包含 UI for ASP.NET Core。

© . All rights reserved.