在 Razor 文件中,Tag Helpers 能够让服务端代码参与创建和渲染 HTML 元素。
Tag Helpers通过丰富的智能感知环境来创建 HTML 和 Razor 标记,为我们提供了友好的开发体验,同时让生成的代码更加高效、可靠,可维护。
Tag Helpers的内容比较多,特地整理一下。。。
直接举例:
<form asp-controller="Demo" asp-action="Register" method="post">
form>
生成的HTML:
<form method="post" action="/Demo/Register">
<input name="__RequestVerificationToken" type="hidden" value="" />
form>
MVC 运行时会根据 Form Tag Helper 的属性 asp-controller 和 asp-action 生成 action的属性值。
通过asp-route可以让下面的表单使用路由规则中name为register的路由。
<form asp-route="register" method="post">
form>
生成的HTML:
<form asp-controller="Account" asp-action="Login"
method="post" class="form-horizontal" role="form">
form>
为 asp-for 属性中指定的表达式名称生成 id 和 name 属性。
基于模型类型和应用在模型属性上的 Tpye 特性来设置 HTML type 的属性值。
如果 HTML type 属性已被指定,则不会覆盖它。
根据应用在模型属性上的 验证 特性生成 HTML5 验证属性。
上面第2条说到Tag Helper基于 .NET 类型和特性来设置 HTML type 属性。以下是常见的 .NET 类型和特性生成出的 HTML 类型:
.Net类型生成的HTML类型:
.Net类型 | Input类型 |
---|---|
Bool | type=”checkbox” |
String | type=”text” |
DateTime | type=”datetime” |
Byte | type=”number” |
Int | type=”number” |
Single, Double | type=”number” |
.Net特性生成的HTML类型:
Attribute | Input Type |
---|---|
[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” |
举个栗子:
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">Registerbutton>
form>
上述代码生成如下的 HTML :
<form method="post" action="/Demo/RegisterInput">
Email:
<input type="email" data-val="true"
data-val-email="The Email Address field is not a valid e-mail address."
data-val-required="The Email Address field is required."
id="Email" name="Email" value="" /> <br>
Password:
<input type="password" data-val="true"
data-val-required="The Password field is required."
id="Password" name="Password" /><br>
<button type="submit">Registerbutton>
<input name="__RequestVerificationToken" type="hidden" value="" />
form>
asp-for 属性值是一个 ModelExpression 同时也是 lambda 表达式右边的部分。因此,不需要使用 Model 前缀。
asp-for可以通过视图模型的属性路径定位到子属性。
类代码:
//类A
public class AddressViewModel
{
public string AddressLine { get; set; }
}
//类B中嵌套了类A
public class RegisterAddressViewModel
{
public string Email { get; set; }
[DataType(DataType.Password)]
public string Password { get; set; }
public AddressViewModel Address { get; set; }
}
视图代码:
@model RegisterAddressViewModel
<form asp-controller="Demo" asp-action="RegisterAddress" method="post">
Email: <input asp-for="Email" /> <br />
Password: <input asp-for="Password" /><br />
Address: <input asp-for="Address.AddressLine" /><br />
<button type="submit">Registerbutton>
form>
asp-for是不需要model前缀的,所以直接可以与model中的email等属性绑定。
对于子属性AddressLine,我们可以通过Address.AddressLine来绑定。
<span asp-validation-for="Email"></span>
<span class="field-validation-valid"
data-valmsg-for="Email"
data-valmsg-replace="true">
</span>
通常在模型属性相同的 Input Tag Helper后面使用 Validation Message Tag Helper 。这样可以在发生验证错误的 input 旁边显示错误信息。
HTML Helper 替代选项: Html.ValidationMessageFor()
Select Tag Helper 的 asp-for 为 select 元素指定模型的属性名称,而 asp-items 则指定 option 元素。
类代码:
public class CountryViewModel
{
public string Country { get; set; }
public List Countries { get; } = new List
{
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);
}
index视图:
@model CountryViewModel
<form asp-controller="Home" asp-action="Index" method="post">
<select asp-for="Country" asp-items="Model.Countries">select>
<br /><button type="submit">Registerbutton>
form>
生成Html:
上面asp-for指定的模型类型是单值类型,但如果指定的模型换成一个 IEnumerable 类型, Select Tag Helper 将会在HTML中自动生成 multiple = “multiple”。
注意:只要asp-for 是一个特例,不需要 Model 前缀。
当选项分组时,会生成 HTML < optgroup > 元素:
public class CountryViewModelGroup
{
public CountryViewModelGroup()
{
var AmericaGroup = new SelectListGroup { Name = "America" };
var EuropeGroup = new SelectListGroup { Name = "Europe" };
public string Country { get; set; }
public List Countries { get; } = new List
{
new SelectListItem
{
Value = "CAN",
Text = "Canada",
Group = AmericaGroup
},
new SelectListItem
{
Value = "US",
Text = "USA",
Group = AmericaGroup
},
new SelectListItem
{
Value = "FR",
Text = "France",
Group = EuropeGroup
},
new SelectListItem
{
Value = "ES",
Text = "Spain",
Group = EuropeGroup
},
};
}
}
其余操作与上面Select Tag Helper类似。。。
public enum CountryEnum
{
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
public class CountryEnumViewModel
{
public CountryEnum EnumCountry { get; set; }
}
视图:
@model CountryEnumViewModel
<form asp-controller="Home" asp-action="IndexEnum" method="post">
<select asp-for="EnumCountry"
asp-items="Html.GetEnumSelectList()" > >
select>
<br /><button type="submit">Registerbutton>
form>
生成HTML:
Html.TextBox、Html.TextBoxFor、Html.Editor 和 Html.EditorFor 有着与 Input Tag Helper 重复的功能。
Input Tag Helper 会自动设置 type 属性,而Html.TextBox 和 Html.TextBoxFor 则不会。
Html.Editor 和 Html.EditorFor 会处理集合、复杂对象以及模版,而Input Tag Helper 则不会。
Input Tag Helper 、Html.EditorFor 和 Html.TextBoxFor 是强类型的,但是Html.TextBox 和 Html.Editor 则不是。
HTML Helper 的Html.TextAreaFor、Html.LabelFor 与Textarea Tag Helper、 Label Tag Helper 类似。
Tag Helper和 HTML Helpers 相比,生成的标记干净得多而且更容易阅读,编辑和维护。
创建类继承自TagHelper可以让我们扩展tagHelper的功能:
<email>Supportemail>
//[HtmlTargetElement(Attributes = "email")]
public class EmailTagHelper : TagHelper
{
private const string EmailDomain = "contoso.com";
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "a"; // Replaces with tag
var address = MailTo + "@" + EmailDomain;
output.Attributes.SetAttribute("href", "mailto:" + address);
output.Content.SetContent(address);
}
}
Description:
Tag helper 使用以目标元素名作为根类名,在这个例子中, EmailTagHelper 的根名称是 email ,因此 TagName的默认值就是email。
重写 Process 方法可以控制 Tag Helper 在执行过程中的行为。 TagHelper 类同样提供了相同参数的异步版本(ProcessAsync)。
类名后缀TagHelper是非必需的,但它被认为是最佳惯例约定。
为使自定义的TagHelper在Razor中可用,需要在Views/_ViewImports.cshtml 文件中通过addTagHelper指令添加包含自定义TagHelper的命名空间。
[HtmlTargetElement] 属性传递一个属性参数,指定为任何 HTML 元素包含名为 “bold” 的 HTML 属性。例如:同时使用[HtmlTargetElement(“email”)]和[HtmlTargetElement(Attributes = “email”)],bold 标签和bold 属性都会被匹配。
//异步Process
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "a"; // Replaces with tag
var content = await output.GetChildContentAsync();
var target = content.GetContent() + "@" + EmailDomain;
output.Attributes.SetAttribute("href", "mailto:" + target);
output.Content.SetContent(target);
}
ASP.NET Core 中文文档 第四章 MVC(3.4)如何使用表单:
http://www.cnblogs.com/dotNETCoreSG/p/aspnetcore-4_3_4-working-with-forms.html
ASP.NET Core 中文文档 第四章 MVC(3.6.1 )Tag Helpers 介绍:
http://www.cnblogs.com/dotNETCoreSG/p/aspnetcore-4_3_6_1-introduction-to-tag-helpers.html
ASP.NET Core 中文文档 第四章 MVC(3.6.2 )自定义标签辅助类(Tag Helpers):
http://www.cnblogs.com/dotNETCoreSG/p/aspnetcore-4_3_6_2-tag-helpers-authoring.html