Tag Helpers trong Forms trong ASP.NET Core
Bởi Rick Anderson, N. Taylor Mullen, Dave Paquette, và Jerrie Pelser
Tài liệu này hướng dẫn cách làm việc với Forms (biểu mẫu) và các phần tử HTML thường dùng trong Form. Phần tử HTML Form cung cấp cơ chế chính mà các ứng dụng web dùng để gửi dữ liệu ngược về server. Phần lớn tài liệu này mô tả Tag Helpers và cách chúng giúp bạn tạo các HTML form mạnh mẽ một cách hiệu quả. Bạn nên đọc Giới thiệu về Tag Helpers trước khi đọc tài liệu này.
Trong nhiều trường hợp, HTML Helpers cung cấp một cách tiếp cận thay thế cho một Tag Helper cụ thể. Tuy nhiên, điều quan trọng cần nhận ra là Tag Helpers không thay thế HTML Helpers, và không có Tag Helper cho mỗi HTML Helper. Khi có HTML Helper thay thế, nó sẽ được đề cập.
Form Tag Helper
- Tạo giá trị thuộc tính HTML
actioncủa<FORM>cho một controller action hoặc named route của MVC. - Tạo hidden Request Verification Token để ngăn chặn cross-site request forgery (khi dùng với thuộc tính
[ValidateAntiForgeryToken]trong HTTP Post action method). - Cung cấp thuộc tính
asp-route-<Tên Tham Số>, trong đó<Tên Tham Số>được thêm vào route values. Các tham sốrouteValuescủaHtml.BeginFormvàHtml.BeginRouteFormcung cấp chức năng tương tự. - Có HTML Helper thay thế là
Html.BeginFormvàHtml.BeginRouteForm.
Ví dụ:
<form asp-controller="Demo" asp-action="Register" method="post">
<!-- Input and Submit elements -->
</form>Form Tag Helper ở trên tạo ra HTML sau:
<form method="post" action="/Demo/Register">
<!-- Input and Submit elements -->
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>MVC runtime tạo giá trị thuộc tính action từ các thuộc tính asp-controller và asp-action của Form Tag Helper. Form Tag Helper cũng tạo hidden Request Verification Token để ngăn chặn cross-site request forgery (khi dùng với thuộc tính [ValidateAntiForgeryToken] trong HTTP Post action method). Bảo vệ một HTML Form thuần khỏi cross-site request forgery rất khó, nhưng Form Tag Helper cung cấp dịch vụ này cho bạn.
Sử dụng named route
Thuộc tính Tag Helper asp-route cũng có thể tạo markup cho thuộc tính action của HTML. Một ứng dụng có route tên là register có thể dùng markup sau cho trang đăng ký:
<form asp-route="register" method="post">
<!-- Input and Submit elements -->
</form>Nhiều view trong thư mục Views/Account (được tạo khi bạn tạo ứng dụng web mới với Individual Accounts) chứa thuộc tính asp-route-returnurl:
<form asp-controller="Account" asp-action="Login"
asp-route-returnurl="@ViewData["ReturnUrl"]"
method="post" class="form-horizontal" role="form">Với các template tích hợp sẵn, returnUrl chỉ được điền tự động khi bạn cố gắng truy cập tài nguyên được ủy quyền nhưng chưa được xác thực hoặc ủy quyền. Khi bạn cố truy cập trái phép, middleware bảo mật chuyển hướng bạn đến trang đăng nhập với returnUrl được đặt.
Form Action Tag Helper
Form Action Tag Helper tạo thuộc tính formaction trên thẻ <button ...> hoặc <input type="image" ...> được tạo ra. Thuộc tính formaction điều khiển nơi form gửi dữ liệu. Nó liên kết với các phần tử <input> kiểu image và các phần tử <button>. Form Action Tag Helper cho phép sử dụng nhiều thuộc tính asp- của AnchorTagHelper để kiểm soát liên kết formaction nào được tạo cho phần tử tương ứng.
Các thuộc tính AnchorTagHelper được hỗ trợ để kiểm soát giá trị formaction:
| Thuộc tính | Mô tả |
|---|---|
| asp-controller | Tên của controller. |
| asp-action | Tên của action method. |
| asp-area | Tên của area. |
| asp-page | Tên của Razor page. |
| asp-page-handler | Tên của Razor page handler. |
| asp-route | Tên của route. |
| asp-route-{value} | Một giá trị URL route đơn. Ví dụ: asp-route-id="1234". |
| asp-all-route-data | Tất cả route values. |
| asp-fragment | Fragment của URL. |
Ví dụ gửi đến controller
Markup sau gửi form đến action Index của HomeController khi input hoặc button được chọn:
<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>Markup trên tạo ra HTML sau:
<form method="post">
<button formaction="/Home">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home">
</form>Ví dụ gửi đến page
Markup sau gửi form đến Razor Page About:
<form method="post">
<button asp-page="About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-page="About">
</form>Markup trên tạo ra HTML sau:
<form method="post">
<button formaction="/About">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/About">
</form>Ví dụ gửi đến route
Xét endpoint /Home/Test:
public class HomeController : Controller
{
[Route("/Home/Test", Name = "Custom")]
public string Test()
{
return "This is the test page";
}
}Markup sau gửi form đến endpoint /Home/Test.
<form method="post">
<button asp-route="Custom">Click Me</button>
<input type="image" src="..." alt="Or Click Me" asp-route="Custom">
</form>Markup trên tạo ra HTML sau:
<form method="post">
<button formaction="/Home/Test">Click Me</button>
<input type="image" src="..." alt="Or Click Me" formaction="/Home/Test">
</form>Input Tag Helper
Input Tag Helper liên kết một phần tử HTML <input> với một model expression trong Razor view.
Cú pháp:
<input asp-for="<Expression Name>">
Input Tag Helper:
- Tạo các thuộc tính HTML
idvànamecho tên expression được chỉ định trong thuộc tínhasp-for.asp-for="Property1.Property2"tương đương vớim => m.Property1.Property2. Tên của expression được dùng làm giá trị thuộc tínhasp-for. Xem phần Tên expression để biết thêm thông tin. - Đặt giá trị thuộc tính HTML
typedựa trên kiểu model và các thuộc tính data annotation được áp dụng cho thuộc tính model. - Không ghi đè giá trị thuộc tính HTML
typekhi đã được chỉ định. - Tạo các thuộc tính xác thực HTML5 từ các thuộc tính data annotation được áp dụng cho các thuộc tính model.
- Có tính năng HTML Helper trùng với
Html.TextBoxForvàHtml.EditorFor. Xem phần HTML Helper alternatives to Input Tag Helper để biết chi tiết. - Cung cấp strong typing (kiểu dữ liệu mạnh). Nếu tên thuộc tính thay đổi và bạn không cập nhật Tag Helper, bạn sẽ nhận được lỗi tương tự như sau:
``` An error occurred during the compilation of a resource required to process this request. Please review the following specific error details and modify your source code appropriately.
Type expected 'RegisterViewModel' does not contain a definition for 'Email' and no extension method 'Email' accepting a first argument of type 'RegisterViewModel' could be found (are you missing a using directive or an assembly reference?) ```
Input Tag Helper đặt thuộc tính HTML type dựa trên kiểu .NET. Bảng sau liệt kê một số kiểu .NET phổ biến và kiểu input HTML được tạo (không phải tất cả kiểu .NET đều được liệt kê):
| Kiểu .NET | Kiểu Input |
|---|---|
| Bool | type="checkbox" |
| String | type="text" |
| DateTime | type="datetime-local" |
| Byte | type="number" |
| Int | type="number" |
| Single, Double | type="number" |
Bảng sau hiển thị một số thuộc tính data annotations phổ biến mà input tag helper sẽ ánh xạ sang các kiểu input cụ thể:
| Thuộc tính | Kiểu Input |
|---|---|
| [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" |
Ví dụ:
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">
<label>Email: <input asp-for="Email" /></label> <br />
<label>Password: <input asp-for="Password" /></label><br />
<button type="submit">Register</button>
</form>Code trên tạo ra HTML sau:
<form method="post" action="/Demo/RegisterInput">
Email:
<input type="email" data-val="true"
data-val-email="The Email Address field is not a valid email 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>Các data annotations được áp dụng cho các thuộc tính Email và Password tạo metadata trên model. Input Tag Helper sử dụng metadata model và tạo các thuộc tính data-val-* của HTML5 (xem Model Validation). Các thuộc tính này mô tả các validator được đính kèm vào input fields. Điều này cung cấp xác thực HTML5 không xâm phạm và jQuery. Các thuộc tính không xâm phạm có định dạng data-val-rule="Error Message", trong đó rule là tên quy tắc xác thực (ví dụ: data-val-required, data-val-email, data-val-maxlength, v.v.).
Khi liên kết nhiều điều khiển input với cùng một thuộc tính, các điều khiển được tạo ra sẽ dùng chung id, làm cho markup được tạo không hợp lệ. Để ngăn chặn trùng lặp, hãy chỉ định thuộc tính id cho mỗi điều khiển một cách rõ ràng.
Hiển thị hidden input cho Checkbox
Checkbox trong HTML5 không gửi giá trị khi chưa được chọn. Để cho phép gửi giá trị mặc định cho checkbox chưa chọn, Input Tag Helper tạo thêm một hidden input cho checkbox.
Ví dụ, xét Razor markup sau dùng Input Tag Helper cho thuộc tính model boolean IsChecked:
<form method="post">
<input asp-for="@Model.IsChecked" />
<button type="submit">Submit</button>
</form>Razor markup trên tạo ra HTML markup tương tự như sau:
<form method="post">
<input name="IsChecked" type="checkbox" value="true" />
<button type="submit">Submit</button>
<input name="IsChecked" type="hidden" value="false" />
</form>HTML markup trên hiển thị thêm một hidden input với tên IsChecked và giá trị false. Mặc định, hidden input này được hiển thị ở cuối form. Khi form được submit:
- Nếu checkbox
IsCheckedđược chọn, cảtruevàfalseđều được gửi làm giá trị. - Nếu checkbox
IsCheckedkhông được chọn, chỉ giá trịfalsecủa hidden input được gửi.
Quá trình model-binding của ASP.NET Core chỉ đọc giá trị đầu tiên khi liên kết với giá trị bool, kết quả là true cho checkbox được chọn và false cho checkbox không được chọn.
Để cấu hình hành vi hiển thị hidden input, đặt thuộc tính CheckBoxHiddenInputRenderMode trên MvcViewOptions.HtmlHelperOptions. Ví dụ:
services.Configure<MvcViewOptions>(options =>
options.HtmlHelperOptions.CheckBoxHiddenInputRenderMode =
CheckBoxHiddenInputRenderMode.None);Code trên vô hiệu hóa hiển thị hidden input cho checkbox bằng cách đặt CheckBoxHiddenInputRenderMode thành CheckBoxHiddenInputRenderMode.None.
HTML Helper alternatives cho Input Tag Helper
Html.TextBox, Html.TextBoxFor, Html.Editor, và Html.EditorFor có các tính năng trùng lặp với Input Tag Helper. Input Tag Helper sẽ tự động đặt thuộc tính type; Html.TextBox và Html.TextBoxFor thì không. Html.Editor và Html.EditorFor xử lý collections, complex objects, và templates; Input Tag Helper không làm vậy. Input Tag Helper, Html.EditorFor, và Html.TextBoxFor là strongly typed (chúng dùng lambda expressions); Html.TextBox và Html.Editor thì không (chúng dùng expression names).
HtmlAttributes
@Html.Editor() và @Html.EditorFor() sử dụng một mục ViewDataDictionary đặc biệt có tên htmlAttributes khi thực thi các template mặc định của chúng. Hành vi này có thể được bổ sung tùy chọn bằng cách dùng tham số additionalViewData. Khóa "htmlAttributes" không phân biệt hoa thường.
@Html.EditorFor(model => model.YourProperty,
new { htmlAttributes = new { @class="myCssClass", style="Width:100px" } })Tên Expression
Giá trị thuộc tính asp-for là một ModelExpression và phần bên phải của lambda expression. Do đó, asp-for="Property1" trở thành m => m.Property1 trong code được tạo, đó là lý do tại sao bạn không cần tiền tố Model. Bạn có thể dùng ký tự "@" để bắt đầu inline expression và di chuyển trước m.:
@{
var joe = "Joe";
}
<input asp-for="@joe">Tạo ra:
<input type="text" id="joe" name="joe" value="Joe">
Với collection properties, asp-for="CollectionProperty[23].Member" tạo ra tên giống như asp-for="CollectionProperty[i].Member" khi i có giá trị 23.
Khi ASP.NET Core MVC tính giá trị của ModelExpression, nó kiểm tra nhiều nguồn, bao gồm ModelState. Xét <input type="text" asp-for="Name">. Giá trị thuộc tính value được tính toán là giá trị không null đầu tiên từ:
- Mục
ModelStatevới khóa "Name". - Kết quả của expression
Model.Name.
Điều hướng đến thuộc tính con
Bạn cũng có thể điều hướng đến các thuộc tính con bằng cách dùng property path của view model. Xét một model class phức tạp hơn có chứa thuộc tính Address con.
public class AddressViewModel
{
public string AddressLine1 { get; set; }
}public class RegisterAddressViewModel
{
public string Email { get; set; }
[DataType(DataType.Password)]
public string Password { get; set; }
public AddressViewModel Address { get; set; }
}Trong view, chúng ta liên kết với Address.AddressLine1:
@model RegisterAddressViewModel
<form asp-controller="Demo" asp-action="RegisterAddress" method="post">
<label>Email: <input asp-for="Email" /></label> <br />
<label>Password: <input asp-for="Password" /></label><br />
<label>Address: <input asp-for="Address.AddressLine1" /></label><br />
<button type="submit">Register</button>
</form>HTML sau được tạo cho Address.AddressLine1:
<input type="text" id="Address_AddressLine1" name="Address.AddressLine1" value="">
Tên Expression và Collections
Ví dụ, một model chứa array of Colors:
public class Person
{
public List<string> Colors { get; set; }
public int Age { get; set; }
}Action method:
public IActionResult Edit(int id, int colorIndex)
{
ViewData["Index"] = colorIndex;
return View(GetPerson(id));
}Razor sau cho thấy cách bạn truy cập một phần tử Color cụ thể:
@model Person
@{
var index = (int)ViewData["index"];
}
<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>Template Views/Shared/EditorTemplates/String.cshtml:
@model string <label asp-for="@Model"></label> <input asp-for="@Model" /> <br />
Ví dụ sử dụng List<T>:
public class ToDoItem
{
public string Name { get; set; }
public bool IsDone { get; set; }
}Razor sau cho thấy cách lặp qua một collection:
@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>Template Views/Shared/EditorTemplates/ToDoItem.cshtml:
@model ToDoItem
<td>
<label asp-for="@Model.Name"></label>
@Html.DisplayFor(model => model.Name)
</td>
<td>
<input asp-for="@Model.IsDone" />
</td>foreach nên được sử dụng khi có thể khi giá trị sẽ được sử dụng trong ngữ cảnh asp-for hoặc tương đương Html.DisplayFor. Nói chung, for tốt hơn foreach (nếu kịch bản cho phép) vì nó không cần cấp phát enumerator; tuy nhiên, đánh giá một indexer trong LINQ expression có thể tốn kém và nên được giảm thiểu.
Textarea Tag Helper
Textarea Tag Helper tương tự như Input Tag Helper.
- Tạo các thuộc tính
idvàname, và các thuộc tính data validation từ model cho phần tử<textarea>. - Cung cấp strong typing.
- HTML Helper thay thế:
Html.TextAreaFor.
Ví dụ:
using System.ComponentModel.DataAnnotations;
namespace FormsTagHelper.ViewModels
{
public class DescriptionViewModel
{
[MinLength(5)]
[MaxLength(1024)]
public string Description { get; set; }
}
}@model DescriptionViewModel
<form asp-controller="Demo" asp-action="RegisterTextArea" method="post">
<textarea asp-for="Description"></textarea>
<button type="submit">Test</button>
</form>HTML sau được tạo ra:
<form method="post" action="/Demo/RegisterTextArea"> <textarea data-val="true" data-val-maxlength="The field Description must be a string or array type with a maximum length of '1024'." data-val-maxlength-max="1024" data-val-minlength="The field Description must be a string or array type with a minimum length of '5'." data-val-minlength-min="5" id="Description" name="Description"> </textarea> <button type="submit">Test</button> <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>"> </form>
Label Tag Helper
- Tạo caption nhãn và thuộc tính
fortrên phần tử<label>cho tên expression. - HTML Helper thay thế:
Html.LabelFor.
Label Tag Helper cung cấp các lợi ích sau so với phần tử label HTML thuần:
- Bạn tự động nhận được giá trị nhãn mô tả từ thuộc tính
Display. Tên hiển thị dự kiến có thể thay đổi theo thời gian, và sự kết hợp của thuộc tínhDisplayvà Label Tag Helper sẽ áp dụngDisplayở mọi nơi nó được sử dụng. - Ít markup hơn trong source code.
- Strong typing với model property.
Ví dụ:
using System.ComponentModel.DataAnnotations;
namespace FormsTagHelper.ViewModels
{
public class SimpleViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email Address")]
public string Email { get; set; }
}
}@model SimpleViewModel
<form asp-controller="Demo" asp-action="RegisterLabel" method="post">
<label asp-for="Email"></label>
<input asp-for="Email" /> <br />
</form>HTML sau được tạo cho phần tử <label>:
<label for="Email">Email Address</label>
Label Tag Helper tạo giá trị thuộc tính for là "Email", đây là ID liên kết với phần tử <input>. Tag Helpers tạo ra các phần tử id và for nhất quán để chúng có thể được liên kết đúng cách. Caption trong ví dụ này đến từ thuộc tính Display. Nếu model không chứa thuộc tính Display, caption sẽ là tên thuộc tính của expression.
Validation Tag Helpers
Có hai Validation Tag Helpers. Validation Message Tag Helper (hiển thị thông báo xác thực cho một thuộc tính đơn trong model), và Validation Summary Tag Helper (hiển thị tóm tắt các lỗi xác thực). Input Tag Helper thêm các thuộc tính xác thực client-side HTML5 vào input elements dựa trên các thuộc tính data annotation trên model classes. Xác thực cũng được thực hiện trên server. Validation Tag Helper hiển thị các thông báo lỗi này khi xảy ra lỗi xác thực.
Validation Message Tag Helper
- Thêm thuộc tính HTML5
data-valmsg-for="property"vào phần tửspan, đính kèm thông báo lỗi xác thực vào input field của thuộc tính model được chỉ định. Khi xảy ra lỗi xác thực client-side, jQuery hiển thị thông báo lỗi trong phần tử<span>. - Xác thực cũng diễn ra trên server. Khách hàng có thể đã tắt JavaScript và một số xác thực chỉ có thể được thực hiện ở phía server.
- HTML Helper thay thế:
Html.ValidationMessageFor.
Validation Message Tag Helper được sử dụng với thuộc tính asp-validation-for trên phần tử HTML span.
<span asp-validation-for="Email"></span>
Validation Message Tag Helper sẽ tạo HTML sau:
<span class="field-validation-valid" data-valmsg-for="Email" data-valmsg-replace="true"></span>
Bạn thường sử dụng Validation Message Tag Helper sau Input Tag Helper cho cùng một thuộc tính. Làm như vậy hiển thị bất kỳ thông báo lỗi xác thực nào gần input đã gây ra lỗi.
Bạn phải có view với các tham chiếu script JavaScript và jQuery chính xác cho xác thực client-side. Xem Model Validation để biết thêm thông tin.
Khi xảy ra lỗi xác thực server-side, MVC đặt thông báo lỗi đó làm nội dung của phần tử <span>.
<span class="field-validation-error" data-valmsg-for="Email"
data-valmsg-replace="true">
The Email Address field is required.
</span>Validation Summary Tag Helper
- Nhắm đến các phần tử
<div>với thuộc tínhasp-validation-summary. - HTML Helper thay thế:
@Html.ValidationSummary.
Validation Summary Tag Helper được sử dụng để hiển thị tóm tắt thông báo xác thực. Giá trị thuộc tính asp-validation-summary có thể là một trong các giá trị sau:
| asp-validation-summary | Thông báo xác thực được hiển thị |
|---|---|
All | Cấp độ thuộc tính và model |
ModelOnly | Chỉ model |
None | Không có |
Ví dụ
Trong ví dụ sau, data model có các thuộc tính DataAnnotation, tạo thông báo lỗi xác thực trên phần tử <input>. Khi xảy ra lỗi xác thực, Validation Tag Helper hiển thị thông báo lỗi:
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>
<label>Email: <input asp-for="Email" /></label> <br />
<span asp-validation-for="Email"></span><br />
<label>Password: <input asp-for="Password" /></label><br />
<span asp-validation-for="Password"></span><br />
<button type="submit">Register</button>
</form>HTML được tạo ra (khi model hợp lệ):
<form action="/DemoReg/Register" method="post"> <label>Email: <input name="Email" id="Email" type="email" value="" data-val-required="The Email field is required." data-val-email="The Email field is not a valid email address." data-val="true"></label><br> <span class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="Email"></span><br> <label>Password: <input name="Password" id="Password" type="password" data-val-required="The Password field is required." data-val="true"></label><br> <span class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="Password"></span><br> <button type="submit">Register</button> <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>"> </form>
Select Tag Helper
- Tạo các phần tử select và option liên quan cho các thuộc tính của model.
- Có HTML Helper thay thế
Html.DropDownListForvàHtml.ListBoxFor.
Select Tag Helper asp-for chỉ định tên thuộc tính model cho phần tử select và asp-items chỉ định các phần tử option. Ví dụ:
<select asp-for="Country" asp-items="Model.Countries"></select>
Ví dụ:
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" },
};
}
}Method Index khởi tạo CountryViewModel, đặt quốc gia được chọn, và truyền nó đến view Index.
public IActionResult Index()
{
var model = new CountryViewModel();
model.Country = "CA";
return View(model);
}Method Index HTTP POST hiển thị lựa chọn:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(CountryViewModel model)
{
if (ModelState.IsValid)
{
var msg = model.Country + " selected";
return RedirectToAction("IndexSuccess", new { message = msg });
}
// If we got this far, something failed; redisplay form.
return View(model);
}View 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>Tạo ra HTML sau (với "CA" được chọn):
<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>Chúng tôi không khuyến nghị sử dụng ViewBag hoặc ViewData với Select Tag Helper. View model mạnh mẽ hơn trong việc cung cấp MVC metadata và ít gây rắc rối hơn.
Enum binding (Liên kết enum)
Thường tiện lợi khi sử dụng <select> với thuộc tính enum và tạo các phần tử SelectListItem từ các giá trị enum.
Ví dụ:
public class CountryEnumViewModel
{
public CountryEnum EnumCountry { get; set; }
}using System.ComponentModel.DataAnnotations;
namespace FormsTagHelper.ViewModels
{
public enum CountryEnum
{
[Display(Name = "United Mexican States")]
Mexico,
[Display(Name = "United States of America")]
USA,
Canada,
France,
Germany,
Spain
}
}Method GetEnumSelectList tạo một đối tượng SelectList cho enum.
@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 sau được tạo ra:
<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">United Mexican States</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>Option Group
Phần tử HTML <optgroup> được tạo khi view model chứa một hoặc nhiều đối tượng SelectListGroup.
CountryViewModelGroup nhóm các phần tử SelectListItem vào các nhóm "North America" và "Europe":
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; }
}HTML được tạo ra:
<form method="post" action="/Home/IndexGroup">
<select id="Country" name="Country">
<optgroup label="North America">
<option value="MEX">Mexico</option>
<option value="CAN">Canada</option>
<option value="US">USA</option>
</optgroup>
<optgroup label="Europe">
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</optgroup>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>Multiple select (Chọn nhiều)
Select Tag Helper sẽ tự động tạo thuộc tính multiple="multiple" nếu thuộc tính được chỉ định trong asp-for là IEnumerable. Ví dụ, với model sau:
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace FormsTagHelper.ViewModels
{
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"}
};
}
}Với view sau:
@model CountryViewModelIEnumerable
<form asp-controller="Home" asp-action="IndexMultiSelect" method="post">
<select asp-for="CountryCodes" asp-items="Model.Countries"></select>
<br /><button type="submit">Register</button>
</form>Tạo ra HTML sau:
<form method="post" action="/Home/IndexMultiSelect">
<select id="CountryCodes"
multiple="multiple"
name="CountryCodes"><option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>Không có lựa chọn
Nếu bạn thấy mình dùng tùy chọn "not specified" trên nhiều trang, bạn có thể tạo template để tránh lặp lại HTML:
@model CountryViewModel
<form asp-controller="Home" asp-action="IndexEmpty" method="post">
@Html.EditorForModel()
<br /><button type="submit">Register</button>
</form>Template Views/Shared/EditorTemplates/CountryViewModel.cshtml:
@model CountryViewModel
<select asp-for="Country" asp-items="Model.Countries">
<option value="">--none--</option>
</select>Phần tử <option> được chọn đúng (chứa thuộc tính selected="selected") tùy thuộc vào giá trị Country hiện tại.
<form method="post" action="/Home/IndexEmpty">
<select id="Country" name="Country">
<option value=""><none></option>
<option value="MX">Mexico</option>
<option value="CA" selected="selected">Canada</option>
<option value="US">USA</option>
</select>
<br /><button type="submit">Register</button>
<input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>