TagHelpers 标记帮助程序
什么是标记帮助程序?
标记帮助程序使服务器端代码可以在 Razor 文件中参与创建和呈现 HTML 元素。
例如,内置 ImageTagHelper
可以将版本号追加到图像名称。 每当图像发生变化时,服务器都会为图像生成一个新的唯一版本,因此客户端总能获得当前图像(而不是过时的缓存图像)。
标记帮助程序使用 C# 创建,基于元素名称、属性名称或父标记以 HTML 元素为目标。
标记帮助程序可以减少 Razor 视图中 HTML 和 C# 之间的显式转换。
标记帮助程序的功能
HTML 易用开发体验
使用标记帮助程序的 Razor 标记在很大程度上看起来像是标准 HTML。 熟悉 HTML/CSS/JavaScript 的前端设计师无需学习 C# Razor 语法即可编辑 Razor。
用于创建 HTML 和 Razor 标记的丰富 IntelliSense 环境
使用仅在服务器上可用的信息,可提高生产力,并能生成更稳定、可靠和可维护的代码
ASP.NET Core 表单中的标记帮助程序
HTML Form 元素提供 Web 应用用于向服务器回发数据的主要机制。
-
为 MVC 控制器操作或命名路由生成 HTML <FORM>>
action
属性值 -
生成隐藏的请求验证令牌,防止跨站点请求伪造(在 HTTP Post 操作方法中与
[ValidateAntiForgeryToken]
属性配合使用时) -
提供
asp-route-<Parameter Name>
属性,其中<Parameter Name>
添加到路由值。Html.BeginForm
和Html.BeginRouteForm
的routeValues
参数提供类似的功能。 -
具有 HTML 帮助程序替代项
Html.BeginForm
和Html.BeginRouteForm
<form asp-controller="Demo" asp-action="Register" method="post"> <!-- Input and Submit elements --> </form>
表单标记帮助程序还会生成隐藏的请求验证令牌,防止跨站点请求伪造(在 HTTP Post 操作方法中与 [ValidateAntiForgeryToken]
属性配合使用时)。 保护纯 HTML 表单免受跨站点请求伪造的影响很难,但表单标记帮助程序可提供此服务。
使用命名路由
<form asp-route="register" method="post"> <!-- Input and Submit elements --> </form>
Views/Account 文件夹中的许多视图(在新建使用个人用户帐户身份验证的 Web 应用时生成)包含 asp-route-returnurl 属性:
<form asp-controller="Account" asp-action="Login" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form">
窗体操作标记帮助程序
窗体操作标记帮助程序在生成的 <button ...>
或 <input type="image" ...>
标记上生成 formaction
属性。 formaction
属性控制窗体在何处提交数据。
用于控制 formaction
值的受支持的 AnchorTagHelper 属性:
属性 | 说明 |
---|---|
asp-controller | 控制器的名称。 |
asp-action | 操作方法的名称。 |
asp-area | 区域名称。 |
asp-page | Razor 页面的名称。 |
asp-page-handler | Razor 页面处理程序的名称。 |
asp-route | 路由的名称。 |
asp-route-{value} | 单个 URL 路由值。 例如,asp-route-id="1234" 。 |
asp-all-route-data | 所有路由值。 |
asp-fragment | URL 片段 |
提交到控制器示例
<form method="post"> <button asp-controller="Home" asp-action="Index">Click Me</button> <input type="image" src="..." alt="Or Click Me" asp-controller="Home" asp-action="Index"> </form>
提交到路由示例
请考虑使用 /Home/Test
终结点:
public class HomeController : Controller { [Route("/Home/Test", Name = "Custom")] public string Test() { return "This is the test page"; } }
以下标记将窗体提交到 /Home/Test
终结点。
<form method="post"> <button asp-route="Custom">Click Me</button> <input type="image" src="..." alt="Or Click Me" asp-route="Custom"> </form>
之前的标记将生成以下 HTML:
<form method="post"> <button formaction="/Home/Test">Click Me</button> <input type="image" src="..." alt="Or Click Me" formaction="/Home/Test"> </form>
输入标记帮助程序
输入标记帮助程序将 HTML <input> 元素绑定到 Razor 视图中的模型表达式。
语法:
<input asp-for="<Expression Name>">
输入标记帮助程序:
-
为
asp-for
属性中指定的表达式名称生成id
和name
HTML 属性。asp-for="Property1.Property2"
等效于m => m.Property1.Property2
。 表达式的名称用于asp-for
属性值。 -
根据模型类型和应用于模型属性的数据注释特性设置 HTML
type
特性值 -
如果已经指定,不会覆盖 HTML
type
属性值 -
具有与
Html.TextBoxFor
和Html.EditorFor
重叠的 HTML 帮助程序功能。 -
提供强类型化。 如果属性的名称更改,但未更新标记帮助程序,则会收到类似如下内容的错误:
Input
标记帮助程序根据 .NET 类型设置 HTML type
属性。 下表列出一些常见的 .NET 类型和生成的 HTML 类型(并未列出每个 .NET 类型)。
.NET 类型 | 输入类型 |
---|---|
Bool | type="checkbox" |
String | type="text" |
DateTime | type="datetime-local" |
Byte | type="number" |
int | type="number" |
Single、Double | type="number" |
下表显示输入标记帮助程序会映射到特定输入类型的一些常见数据注释属性(并未列出每个验证属性):
Attribute | 输入类型 |
---|---|
[EmailAddress] | type="email" |
[Url] | type="url" |
[HiddenInput] | type="hidden" |
[Phone] | type="tel" |
[DataType(DataType.Password)] | type="password" |
[DataType(DataType.Date)] | type="date" |
[DataType(DataType.Time)] | type="time" |
using System.ComponentModel.DataAnnotations; namespace FormsTagHelper.ViewModels { public class RegisterViewModel { [Required] [EmailAddress] [Display(Name = "Email Address")] public string Email { get; set; } [Required] [DataType(DataType.Password)] public string Password { get; set; } } }
@model RegisterViewModel <form asp-controller="Demo" asp-action="RegisterInput" method="post"> Email: <input asp-for="Email" /> <br /> Password: <input asp-for="Password" /><br /> <button type="submit">Register</button> </form>
表达式名称和集合
<form asp-controller="ToDo" asp-action="Edit" method="post"> @Html.EditorFor(m => m.Colors[index]) <label asp-for="Age"></label> <input asp-for="Age" /><br /> <button type="submit">Post</button> </form>
@model List<ToDoItem> <form asp-controller="ToDo" asp-action="Edit" method="post"> <table> <tr> <th>Name</th> <th>Is Done</th> </tr> @for (int i = 0; i < Model.Count; i++) { <tr> @Html.EditorFor(model => model[i]) </tr> } </table> <button type="submit">Save</button> </form>
@model ToDoItem <td> <label asp-for="@Model.Name"></label> @Html.DisplayFor(model => model.Name) </td> <td> <input asp-for="@Model.IsDone" /> </td> @* This template replaces the following Razor which evaluates the indexer three times. <td> <label asp-for="@Model[i].Name"></label> @Html.DisplayFor(model => model[i].Name) </td> <td> <input asp-for="@Model[i].IsDone" /> </td> *@
验证标记帮助程序
<span asp-validation-for="Email"></span>
验证摘要标记帮助程序
using System.ComponentModel.DataAnnotations; namespace FormsTagHelper.ViewModels { public class RegisterViewModel { [Required] [EmailAddress] [Display(Name = "Email Address")] public string Email { get; set; } [Required] [DataType(DataType.Password)] public string Password { get; set; } } }
@model RegisterViewModel <form asp-controller="Demo" asp-action="RegisterValidation" method="post"> <div asp-validation-summary="ModelOnly"></div> Email: <input asp-for="Email" /> <br /> <span asp-validation-for="Email"></span><br /> Password: <input asp-for="Password" /><br /> <span asp-validation-for="Password"></span><br /> <button type="submit">Register</button> </form>
选择标记帮助程序
Select Tag Helper
asp-for
为 select 元素指定模型属性名称,asp-items
指定 option 元素。 例如:
<select asp-for="Country" asp-items="Model.Countries"></select>
using Microsoft.AspNetCore.Mvc.Rendering; using System.Collections.Generic; namespace FormsTagHelper.ViewModels { public class CountryViewModel { public string Country { get; set; } public List<SelectListItem> Countries { get; } = new List<SelectListItem> { new SelectListItem { Value = "MX", Text = "Mexico" }, new SelectListItem { Value = "CA", Text = "Canada" }, new SelectListItem { Value = "US", Text = "USA" }, }; } }
public IActionResult Index() { var model = new CountryViewModel(); model.Country = "CA"; return View(model); }
[HttpPost] [ValidateAntiForgeryToken] public IActionResult Index(CountryViewModel model) { if(ModelState.IsValid) { var msg=model.Country+" selected"; RouteValueDictionary dict = new RouteValueDictionary(); dict.Add("message", msg); return RedirectToAction("IndexSuccess","Country", dict); } return View(model); }
@model CountryViewModel <form asp-controller="Home" asp-action="Index" method="post"> <select asp-for="Country" asp-items="Model.Countries"></select> <br /><button type="submit">Register</button> </form>
枚举绑定
通常可方便地将 <select>
与 enum
属性配合使用并通过 enum
值生成 SelectListItem
元素。
public enum CountryEnum { [Display(Name = "United Mexican States")] Mexico, [Display(Name = "United States of America")] USA, Canada, France, Germany, Spain }
public class CountryEnumViewModel { public CountryEnum EnumCountry { get; set; } }
@model CountryEnumViewModel <form asp-action="IndexEnum" method="post"> <select asp-for="EnumCountry" asp-items="Html.GetEnumSelectList<CountryEnum>()"> </select> <br /> <button type="submit" >Register</button> </form>
选项组
public class CountryViewModelGroup { public CountryViewModelGroup() { var NorthAmericaGroup = new SelectListGroup { Name = "North America" }; var EuropeGroup = new SelectListGroup { Name = "Europe" }; Countries = new List<SelectListItem> { new SelectListItem { Value = "MEX", Text = "Mexico", Group = NorthAmericaGroup }, new SelectListItem { Value = "CAN", Text = "Canada", Group = NorthAmericaGroup }, new SelectListItem { Value = "US", Text = "USA", Group = NorthAmericaGroup }, new SelectListItem { Value = "FR", Text = "France", Group = EuropeGroup }, new SelectListItem { Value = "ES", Text = "Spain", Group = EuropeGroup }, new SelectListItem { Value = "DE", Text = "Germany", Group = EuropeGroup } }; } public string Country { get; set; } public List<SelectListItem> Countries { get; }
@model CountryViewModelGroup <form asp-action="Group"> <select asp-for="Country" asp-items="@Model.Countries"> </select> </form>
多重选择
如果 asp-for
特性中指定的属性为 IEnumerable
,选择标记帮助程序会自动生成 multiple = "multiple" 特性。
public class CountryViewModelIEnumerable { public IEnumerable<string> CountryCodes { get; set; } public List<SelectListItem> Countries { get; } = new List<SelectListItem> { new SelectListItem { Value = "MX", Text = "Mexico" }, new SelectListItem { Value = "CA", Text = "Canada" }, new SelectListItem { Value = "US", Text = "USA" }, new SelectListItem { Value = "FR", Text = "France" }, new SelectListItem { Value = "ES", Text = "Spain" }, new SelectListItem { Value = "DE", Text = "Germany"} }; }
@model CountryViewModelIEnumerable; <form asp-action="Selects" method="post"> <select asp-for="CountryCodes" asp-items="@Model.Countries"> </select> <button type="submit" class="btn btn-primary">提交</button> </form>
无选定内容
@model CountryViewModel <select asp-for="Country" asp-items="Model.Countries"> <option value="">--none--</option> </select>
添加 HTML <选项> 元素并不限于 “无选择 ”大小写。 例如,以下视图和操作方法会生成与上述代码类似的 HTML:
public IActionResult IndexNone() { var model = new CountryViewModel(); model.Insert(0, new SelectListItem("<none>", "")); return View(model); }
根据当前的 Country
值选择正确的 <option>
元素(包含 selected="selected"
属性)。
public IActionResult IndexOption(int id) { var model = new CountryViewModel(); model.Country = "CA"; return View(model); }