.net core Razor视图的TagHelper使用方法介绍

TagHelper

TagHelper是ASP.NET 5的一个新特性。也许在你还没有听说过它的时候, 它已经在技术人员之间引起了大量讨论,甚至有一部分称它为服务器控件的回归。实际上它只不过是一个简化版本,把HTML和服务器内容混合在一起,没有控件生命周期,状态保持和事件。它不像服务器控件那样,对页面所有内容都具有访问权限。它只能访问到自己所生成的内容。

在 Razor 文件中,Tag Helpers 能够让服务端代码参与创建和渲染 HTML 元素。
Tag Helpers通过丰富的智能感知环境来创建 HTML 和 Razor 标记,为我们提供了友好的开发体验,同时让生成的代码更加高效、可靠,可维护。

 

Form TagHelper

直接举例

<form asp-controller="Demo" asp-action="Register" method="post">

</form>

生成的HTML

<form method="post" action="/Demo/Register">

  <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>" />
 </form>

MVC 运行时会根据 Form Tag Helper 的属性 asp-controllerasp-action 生成 action的属性值。

命名路由

通过asp-route可以让下面的表单使用路由规则中name为register的路由。

<form asp-route="register" method="post">
    <!-- Input and Submit elements -->
</form>

生成的HTML:

<form asp-controller="Account" asp-action="Login"
  method="post" class="form-horizontal" role="form">
  <!-- Input and Submit elements -->
</form>

Input TagHelper

作用:

  1. 为 asp-for 属性中指定的表达式名称生成 id 和 name 属性。

  2. 基于模型类型和应用在模型属性上的 Tpye 特性来设置 HTML type 的属性值。

  3. 如果 HTML type 属性已被指定,则不会覆盖它。

  4. 根据应用在模型属性上的 验证 特性生成 HTML5 验证属性。

上面第2条说到TagHelper基于 .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类型:

AttributeInput 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">Register</button>
</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">Register</button>
  <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>" />
</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">Register</button>
</form>

 

asp-for是不需要model前缀的,所以直接可以与model中的email等属性绑定。

对于子属性AddressLine,我们可以通过Address.AddressLine来绑定。

TagHelper验证

<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 TagHelper

Select TagHelper 的 asp-for 为 select 元素指定模型的属性名称,而 asp-items 则指定 option 元素。

类代码:

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);
}

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">Register</button>
</form>

 

生成Html:

<form method="post" action="/">
  <select id="Country" name="Country">
    <option value="MX">Mexico</option>
    <option selected="selected" value="CA">Canada</option>
    <option value="US">USA</option>
  </select>
    <br /><button type="submit">Register</button>
  <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>" />
</form>

上面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<SelectListItem> Countries { get; } = new List<SelectListItem>
         {            
             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类似。。。

Select TagHelper的枚举绑定

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<CountryEnum>()"> >
    </select> 
    <br /><button type="submit">Register</button>
</form>

生成HTML:

<form method="post" action="/Home/IndexEnum">
      <select data-val="true" data-val-required="The EnumCountry field is required."
              id="EnumCountry" name="EnumCountry">
          <option value="0">Mexico</option>
          <option value="1">United States of America</option>
          <option value="2">Canada</option>
          <option value="3">France</option>
          <option value="4">Germany</option>
          <option selected="selected" value="5">Spain</option>
      </select>
      <br /><button type="submit">Register</button>
      <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>" />
 </form>

 

Html Helper与 Input Tag Helper 功能的异同

  1. Html.TextBox、Html.TextBoxFor、Html.Editor 和 Html.EditorFor 有着与 Input Tag Helper 重复的功能。

  2. Input Tag Helper 会自动设置 type 属性,而Html.TextBox 和 Html.TextBoxFor 则不会。

  3. Html.Editor 和 Html.EditorFor 会处理集合、复杂对象以及模版,而Input Tag Helper 则不会。

  4. Input Tag Helper 、Html.EditorFor 和 Html.TextBoxFor 是强类型的,但是Html.TextBox 和 Html.Editor 则不是。

  5. HTML Helper 的Html.TextAreaFor、Html.LabelFor 与Textarea Tag Helper、 Label Tag Helper 类似。

  6. Tag Helper和 HTML Helpers 相比,生成的标记干净得多而且更容易阅读,编辑和维护。

自定义Tag

创建类继承自TagHelper可以让我们扩展tagHelper的功能:

<email>Support</email>
  • 1
//[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 <email> with <a> tag

        var address = MailTo + "@" + EmailDomain;
        output.Attributes.SetAttribute("href", "mailto:" + address);
        output.Content.SetContent(address);
    }
}

 

Description:

  1. Tag helper 使用以目标元素名作为根类名,在这个例子中, EmailTagHelper 的根名称是 email ,因此 TagName的默认值就是email。

  2. 重写 Process 方法可以控制 Tag Helper 在执行过程中的行为。 TagHelper 类同样提供了相同参数的异步版本(ProcessAsync)。

  3. 类名后缀TagHelper是非必需的,但它被认为是最佳惯例约定。

  4. 为使自定义的TagHelper在Razor中可用,需要在Views/_ViewImports.cshtml 文件中通过addTagHelper指令添加包含自定义TagHelper的命名空间。

  5. [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 <email> with <a> tag
    var content = await output.GetChildContentAsync();
    var target = content.GetContent() + "@" + EmailDomain;
    output.Attributes.SetAttribute("href", "mailto:" + target);
    output.Content.SetContent(target);
}
posted @ 2018-08-23 21:33  君吟  阅读(2501)  评论(0编辑  收藏  举报