C# cơ bản .NET Core

Tag Helper trong ASP.NET Core - Razor Page

Các Tag Helper là các phần tử của ngôn ngữ đánh dấu (markup - quen thuộc với các phần tử HTML như <a>, <input> <form> ...), nó được viết trong các View (các file .html, Razor file) , qua đó nó phát sinh mã HTML một cách thích hợp (được gọi là dựng HTML phía server - server side) .

Ví dụ Anchor Tag Helper, giúp bạn phát sinh phần tử <a> với thuộc tính href sinh ra trỏ đến một trang Razor, Control ... Giả sử bạn có trang Razor là ViewProduct, có thiết lập địa chỉ URL là @page "/sanpham/{id?}"

Nếu vậy trong View bạn có thể viết:

<a asp-page="ViewProduct" asp-route-id="2" >Sản phẩm 2</a>

Thì kết quả HTML sinh ra là:

<a href="/sanpham/2" >Sản phẩm 2</a>

asp-page, asp-route-id là thuộc tính của Tag Helper này


Có rất nhiều Tag Helper được xây dựng sẵn cho các tác vụ phổ biến như tạo form, tạo các đường link liên kết ... Các Tag Helper xây dựng sẵn này chủ yếu sử dụng đúng tên thẻ HTML mà nó sinh ra để đặt cho Tag Helper. Như ví dụ trên, khi viết thẻ <a> là sẽ gọi đến Anchor Tag Helper, từ các thuộc tính nó sẽ phát sinh ra giá trị cho href của thẻ <a>

Tag Helper và HTML Helper

Sử dụng Tag Helper giảm thiểu việc sử dụng code C# trong trang Razor (.cshtml), ngoài ra trong các View (.cshtml) còn sử dụng lớp HtmlHelper để phát sinh HTML - nếu dùng Html Helper thì có nghĩa sử dụng trực tiếp mã C#. Trong các View (.cshtml) có thuộc tính Html, bạn có thể truy cập và gọi các phương thức là các Html Helper.

Hãy xét ví dụ sau, để nhận biết cách sử dụng Html Helper và Tag Helper. Giả sử Model của View có thuộc tính như sau:

[DisplayName("Tên người dùng")]
public string UserName { get; set; } = "xuanthulab";

Lúc này để phát sinh HTML tạo ra control của form để nhập liệu (gồm có lable và textbox):

Nếu dùng Html Helper bạn có thể viết (dùng phương thức Lable và TextBox của lớp HtmlHelper)

@Html.Label("UserName")
@Html.TextBox("UserName", null, new {@class = "text-primary"})

Nếu dùng Tag Helper bạn có thể viết (dùng LabelTagHelper, InputTagHelper):

<label asp-for="UserName"></label>
<input asp-for="UserName" class="text-secondary" />

Cả hai cách này đều thu được kết quả là mã HTML như sau:

<label for="UserName">Tên người dùng</label>
<input class="text-secondary" type="text" id="UserName"
    name="UserName" value="xuanthulab" />

Nạp hoặc loại bỏ Tag Helper

(@addTagHelper, @removeTagHelper, !)

Bản chất các Tag Helper cũng là các thư viện lớp .NET, muốn sử dụng Tag Helper trong .cshtml thì phải dùng chỉ thị @addTagHelper để nạp vào.

Mặc định thêm chỉ thị này trong _ViewImports.cshtml (vai trò file _ViewImports) với dòng:

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Ký hiệu * cho biết nạp tất cả các Tag Helper có trong Microsoft.AspNetCore.Mvc.TagHelpers

Nếu muốn vô hiệu hóa một Tag Helper thì dùng chỉ thị @removeTagHelper

Khi bạn viết thẻ HTML, thì Tag Helper tương ứng nếu có sẽ được triệu gọi, nếu muốn hủy tác dụng này thì sử dụng ký tự ! vào trước tên thẻ, ví dụ:

<!label for="UserName">Tên người dùng</!label>

Một số Tag Helper

Dưới đây là một số Tag Helper xây dựng sẵn (trong Microsoft.AspNetCore.Mvc.TagHelpers)

Tag Sử dụng
Anchor

Anchor Tag Helper cải tiến thẻ <a>, bằng cách thêm vào các thuộc tính, các thuộc tính này bắt đầu bằng tiền tố asp-. Từ các thuộc tính asp-, nó sinh ra giá trị cho thuộc tính href, một số thuộc tính đó là:

  • asp-controller Controller (MVC) để phát sinh href của thẻ
  • asp-action Action của controller
  • asp-route-{value} tham số của Route, ví dụ asp-route-id ...
  • asp-route Route để phát sinh href
  • asp-all-route-data thuộc tính gán giá trị bằng đối tượng kiểu Dictionary<string, string> để phát sinh phần query của url
  • asp-fragment phần fragment của URL
  • asp-area tên Area (Xem Area trong ASP.NET Core Razor)
  • asp-page tên trang Razor
  • asp-page-handler thiết lập handler của trang Razor
<a asp-page="ViewProduct" asp-route-id="2">Sản phẩm khác</a>
// Kết quả: <a href="/ViewProduct/2/" >Sản phẩm khác</a>
Form

Cải tiến thẻ <form> với các thuộc tính thêm vào để phát sinh giá trị cho thuộc tính action

asp-controller Tên của controller
asp-action Actionn trong controller
asp-area Tên Area
asp-page Tên trang Razor
asp-page-handler Tên handler của Razor (OnGet, OnPost ..)
asp-route Tên route
asp-route-{value} Giá trị thành phần route
asp-all-route-data Giá trị xây dựng query action
asp-fragment fragment của action form

Bạn có thể sử dụng Input, Button để tạo ActionForm với các thuộc tính trên.

Image

Làm việc trên thẻ <img> với thuộc tính asp-append-version="true" để thêm query v=xxxx vào địa chỉ ảnh.

Chú ý thuộc tính src phải trỏ đến một file tĩnh, ví dụ src="~/images/1.png", nếu vậy nếu asp-append-version="true" thì mỗi phiên bản hình ảnh sẽ cache địa chỉ (phát sinh query v=xxx)

Input

Làm việc trên thẻ <input> với thuộc tính asp-for="@data"

@data là biểu thức, chỉ ra tên dữ liệu.

qua đó nó sinh ra phần tử HTML <input> với các thuộc tính sinh ra là

  • type phần tử sinh ra phụ thuộc vào kiểu data, ví dụ như data là bool thì input có thuộc tính type="checkbox". Ngoài ra kiểu cũng xác định bởi các thuộc tính bổ sung như: [EmailAddress], [DataType(DataType.Time)] ...
  • Phát sinh id dựa vào biểu thức asp-for
Label Làm việc trên thẻ <label> với thuộc tính asp-for="@data"
Link Làm việc trên thẻ <link>
Select Làm việc trên thẻ <select>, ví dụ:
<select asp-for="Country" asp-items="Model.Countries"></select>
Textarea Làm việc trên thẻ <textarea> với thuộc tính asp-for="s"

Tạo Tag Helper riêng

Thực hành tạo ra một Tag Helper, đặt tên thẻ là mylist với dữ liệu truyền vào là list-items là một danh sách chuỗi, list-title tiêu đề, kết quả là phát sinh HTML cấu trúc ul, li như sau:

<h2>Tiêu đề</h2>
<ul class="list-group">
    <li class="list-group-item">item1</li>
    <li class="list-group-item">item2</li>
    ...
</ul>

Để tạo ra một Tag Helper, cần tạo ra lớp kế thừa lớp TagHelper sau đó phải nạp chồng phương thức Process hoặc ProcessAsync nếu dùng bất đồng bộ.


using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Razor.TagHelpers;

namespace XTLAB
{
      // thẻ sẽ là mylist
    [HtmlTargetElement("mylist")]
    public class MyListTagHelper : TagHelper
    {
            // Thuộc tính sẽ là list-title
            public string ListTitle { get; set; }

            // Thuộc tính sẽ là list-items
            public List<string> ListItems {set; get;}

            public override void Process(TagHelperContext context, TagHelperOutput output)
            {
                  output.TagName = "ul";    // ul sẽ thay cho myul
                  output.TagMode = TagMode.StartTagAndEndTag;

                  output.Attributes.SetAttribute("class", "list-group");
                  output.PreElement.AppendHtml($"<h2>{ListTitle}</h2>");


                  StringBuilder content = new StringBuilder();
                  foreach (var item in ListItems)
                  {
                      content.Append($@"<li class=""list-group-item"">{item}</li>");
                  }
                  output.Content.SetHtmlContent(content.ToString());
            }

    }
}

Như vậy đã khai báo xong một Tag Helper. Để nạp và sử dụng chúng hãy cho chỉ thị sau vào file _ViewImports.cshtml

@addTagHelper *, razor04.codebehide

Ở đây razor04.codebehideassembly chứa Helper này. Hãy thay bằng tên dự án của bạn, là file build được từ mã nguồn.

Sử dụng:

@{
   var productlist = new List<String> {
        "Tên Sản phẩm 1",
        "Tên Sản phẩm 2",
        "Tên Sản phẩm 3"
     };
}
<mylist list-title="Danh sách sản phẩm" list-items="@productlist"></mylist>

Kết quả là:

<h2>Danh sách sản phẩm</h2>
<ul class="list-group">
    <li class="list-group-item">Tên Sản phẩm 1</li>
    <li class="list-group-item">Tên Sản phẩm 2</li>
    <li class="list-group-item">Tên Sản phẩm 3</li>
</ul>

Đăng ký nhận bài viết mới