TagHelpers






4.80/5 (3投票s)
本文讨论了 TagHelpers - ASP.NET vNext 中新增的一项功能。
引言
TagHelper 是 ASP.NET MVC 中的一项新功能。如果您还没有听说过,TagHelpers 已经在技术圈中引起了广泛的讨论,有些人声称这是服务器端控件的回归。有人还记得吗?
<asp:TextBox id="txt1" runat="server">
我个人认为 TagHelpers 没有问题,它只是在混合 HTML 和服务器生成内容方面的一种简化,而没有控件生命周期、视图状态、事件等方面的负担。事实上,我认为它是一种更简洁的方法。
免责声明
本文基于 ASP.NET 5(或 vNext)的 beta 版本。情况可能会也一定会发生变化,因此关于 TagHelpers 的一些信息可能已过时。
目的
已经有关于 TagHelpers 的文章了——其中一些非常出色的文章出自 Scott Hanselman 和 Jeffrey T. Fritz(参见资源)。本文在此基础上进一步扩展,因为
- 它提供了基于最新开发版本(v1.0.0-rc1-10798)的更及时信息。
- 它提供了面向开发者的 TagHelpers 视角,包含更多示例。
- 我们通过构建一个示例项目来介绍。我花了些时间才弄清楚各个部分是如何组合在一起的,因为一切都在不断变化,而且文档又不完善,所以这可能会为其他人节省时间。
什么是 TagHelpers?
TagHelpers 允许使用服务器端内容对 HTML 属性进行预处理——也就是说,
<a asp-controller="Home" asp-action="About">About</a>
被转换为
<a href="/Home/About">About</a>
在深入研究之前,让我们先看看当前版本的 MVC 的行为。这将让我们体会到 TagHelpers 的必要性。
在 ASP.NET MVC 5 中,如果我们想声明一个指向另一个页面的链接(anchor 标签),有几种选择。
ActionLink
也许最常见的是使用 HTML 辅助函数 `ActionLink` 方法。有几种重载,我使用的是允许我设置操作、控制器和 HTML 属性的那种。
public static MvcHtmlString ActionLink(
this HtmlHelper htmlHelper,
string linkText,
string actionName,
string controllerName,
Object routeValues,
Object htmlAttributes
)
简单的用法如下:
@Html.ActionLink("About this site",
"About","Home",null,new { @class="someClass"})
Razor & HTML
另一种选择是在 Razor 语法中进行混合搭配。
<a href="@Url.Action("About",
"Home")" class="someClass">About this site</a>
我们也可以创建自己的 Razor 辅助函数或 HTML 辅助函数扩展方法。
虽然这不算坏,但我们的场景很简单,我相信我们都知道将 Razor 语法与 HTML 混合搭配是多么棘手。另一种看待这个问题的方式是,在第一个例子中,我们首先使用了 Razor,然后添加了 HTML 属性,而在第二个例子中,我们首先使用了 HTML,然后添加了 Razor 语法。
AnchorTagHelper
这就是 TagHelper 发挥作用的地方,因为我们不必离开 HTML 的舒适区,同时又能利用 C# 服务器端的强大功能。考虑到上面的相同示例,我们可以重写 anchor 标签为:
<a asp-controller="Home" asp-action="About" class="someClass">About this site</a>
为了简化接下来的过程——MVC 将这个 anchor 传递给一个 C# 类(`AnchorTagHelper`),该类会检查属性并输出服务器生成的 C# 代码。这是混合 HTML 和 C# 代码的一种更简洁的方式。
这与 ASP.NET 服务器端控件不同,尽管语法/概念可能看起来非常相似。主要区别在于:
- 无生命周期事件
- 无视图状态
- 无控件状态
注意:有些文章会提到控制器和操作属性的使用。然而,关于这个问题有一个 讨论,看起来在三种流行的方法中,以 `asp-` 作为前缀的方法已被选定在当前版本中。另外两种选择是使用 `@controller` 或直接使用 `controller`。
TagHelpers 命名空间
ASP.NET 已自带一组内置的 TagHelpers。它们位于 `Microsoft.AspNet.Mvc.TagHelpers` 命名空间中,包括:
Anchor
输入
Label
Select
TextArea
ValidationMessage
ValidationSummary
表单
我们将快速了解所有这些以及它们的基本用法。
AnchorTagHelper
此标签将应用于 `` 锚点元素。目前,它支持以下属性:
asp-action
asp-controller
asp-fragment
asp-host
asp-protocol
asp-route
所有这些都用于为 `` 锚点标签的 `href` 属性生成 URL。
<a asp-controller="Home" asp-action="About">About</a>
如果 `href` 已经在 `` 锚点 HTML 元素中设置,并且设置了 TagHelper 属性,则会抛出异常。因此,例如,下面的代码将抛出异常:
<a href="/Home/Index" asp-controller="Home" asp-action="Index">Home</a>
InputTagHelper
顾名思义,此 `TagHelper` 应用于 `` HTML 元素。它类似于 `TextBoxFor` HTML 扩展方法,因为它会生成一个绑定到模型属性的输入元素。`input` 标签支持以下属性:
asp-for
asp-format
`'asp-for'` 属性引用模型中的属性,并且也用于各种其他 TagHelper。
`'asp-format'` 在检索值后应用格式。这对于货币或日期时间值很有用。例如(`Birthday` 是模型中 `DateTime` 类型的属性)。
<input asp-for="Birthday" asp-format="{0:yyyy-MM-dd}" />
注意:`asp-for` 的类型是 `ModelExpression`,这是 ASP.NET MVC 6 (vNext) 中的一个新类。构造函数接受一个 `string` 参数,该参数会计算为模型中的一个属性。我们还可以引用嵌套对象——例如:
<input asp-for="Address.Street" type="text" /></div>
与 `TextBoxFor` 对比:
@Html.TextBoxFor(model => model.Birthday)
目前,MVC 6 模型绑定器存在一个问题,输入无效日期(`abc`)会显示一个异常消息。
从类型 '`System.String`' 到类型 '`System.DateTime`' 的参数转换失败。请参阅内部异常以获取更多信息。
在 MVC 5 中,异常消息被重新处理成一个更友好的版本,如:
The value 'abc' is not valid for Birthday
LabelTagHelper
与 `HtmlExtension.LabelFor` 方法具有相同的目的——只有一个属性 `'asp-for'`,用于定义模型中的属性(如 `InputTagHelper` 中所述)。它应用于 `
<label asp-for="Birthday" />
SelectTagHelper
`SelectTagHelper` 应用于 `
<select asp-for="Country" asp-items="ViewBag.Countries">
要添加默认项,我们可以这样做:
<select asp-for="Country" asp-items="ViewBag.Countries">
<option selected="selected" value="">Choose Country</option>
</select>
仅供比较,`HtmlHelper` 的做法是:
@Html.DropDownListFor(m=>m.Country, (IEnumerable<SelectListItem>)ViewBag.Countries)
`asp-items` 可以评估视图中可用的任何内容——它可以是对象上的属性、变量等。
我们可以在视图中声明一个变量:
@{
SelectListItem[] items =
{
new SelectListItem() { Text = "item 1" },
new SelectListItem() { Text = "item 2" }
};
}
然后将其用作 `asp-items`:
<select asp-for="Country" asp-items="items">
TextAreaTagHelper
处理 `
<textarea asp-for="Information"></textarea>
ValidationMessageTagHelper
此 TagHelper 用于显示验证错误消息。它与 `ValidationMessageFor` HTML 辅助函数具有相同的目的。这里有趣的问题可能是它适用于哪个 HTML 元素?`ValidationMessageFor` 扩展方法生成了一个 `` 元素,类似地,`ValidationMessageTagHelper` 也应用于 `` 元素。
<span asp-validation-for="Birthday" />
它只有一个属性 `asp-validation-for`,代表模型上的一个字段。
<input asp-for="Birthday" asp-format="{0:yyyy-MM-dd}" />
<span asp-validation-for="Birthday" />
注意:有一个名为 `TagName` 的新属性,它将 C# 类与应用它的 HTML 标签相关联。
[TagName("span")]
public class ValidationMessageTagHelper : TagHelper
ValidationSummaryTagHelper
用于显示验证错误摘要——类似于 HTML 扩展方法 `ValidationSummary`。它只支持一个属性 `asp-validation-summary`,该属性可以具有以下值之一:
- `None`:不显示任何验证消息。
- `ModelOnly`:仅显示 `Model` 错误——不显示属性错误。
- `All`:显示所有消息。
`asp-validation-summary` 应用于 `
<div class="validation" asp-validation-summary="ModelOnly"/>
FormTagHelper
用于生成 `