这篇文章演示了如何使用表单以及表单中常用的 HTML 元素。HTML 的 元素提供了 Web 应用向服务器回发数据的主要机制。本文的大部分在描述 以及它们如何能帮你有效地构建健壮的表单。在阅读本文之前,我们建议你阅读一下 。
在很多情况下, 都提供了对某个 Tag Helper 的替代方法,但重要的是必须意识到 Tag Helper 不是要取代 HTML Helper,而且也并不是每个 HTML Helper 都有对应的 Tag Helper。当一个 HTML Helper 作为替代方案存在时,是有意为之的。
章节:
表单 的 Tag Helper:
特性时)。
- [ValidateAntiForgeryToken]
属性,
- asp-route-<参数名>
是路由里面添加过的值。
- <参数名>
和
- Html.BeginForm
的
- Html.BeginRouteForm
参数提供了类似的功能。
- routeValues
和
- Html.BeginForm
- Html.BeginRouteForm
示例:
- <form asp-controller="Demo" asp-action="Register" method="post">
- <!-- Input and Submit elements -->
- </form>
上面的 Form Tag Helper 生成如下的 HTML :
- <form method="post" action="/Demo/Register">
- <!-- Input and Submit elements -->
- <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>"
- />
- </form>
MVC 运行时(runtime)根据 Form Tag Helper 的属性
和
- asp-controller
生成
- asp-action
属性值。Form Tag Helper 也会生成一个隐藏的 来防止跨站请求伪装(当在 HTTP Post 方法上应用了
- action
特性时)。要保护纯 HTML 避免跨站请求伪装是非常困难的,Form Tag Helper 为你提供了这个服务。
- [ValidateAntiForgeryToken]
Tag Helper 属性
也能为 HTML
- asp-route
属性生成标记。一个应用含有名为
- action
的 可以在注册页面使用如下标记:
- register
- <form asp-route="register" method="post">
- <!-- Input and Submit elements -->
- </form>
Views/Account 文件夹下的很多视图(在你创建一个带有 个人用户账户 的新 Web 应用时生成的)都含有 属性:
- <form asp-controller="Account" asp-action="Login" asp-route-returnurl="@ViewData["
- ReturnUrl "]" method="post" class="form-horizontal" role="form">
注意
采用内建的模版,只有在你尚未经过验证或授权的情况下去尝试访问需授权的资源时,才会被自动填入。当你尝试一个未授权的访问,安全中间件会根据
- returnUrl
的设置将你重定向到登录页面。
- returnUrl
Input Tag Helper 将 HTML 元素绑定到 Razor 视图中的模型表达式上。
语法:
- <input asp-for="<Expression Name>" />
Input Tag Helper:
属性中指定的表达式名称生成
- asp-for
和
- id
HTML 属性。
- name
等价于
- asp-for="Property1.Property2"
,就是说属性值实际上是表达式的一部分。
- m => m.Property1.Property2
属性值所使用的就是表达式的名称。
- asp-for
的属性值。
- type
属性已被指定,则不会覆盖它。
- type
and
- Html.TextBoxFor
功能重叠。详情可参见 Input Tag Helper 的 HTML Helper 替代方法一节。
- Html.EditorFor
- 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 ? )
Tag Helper 基于 .NET 类型来设置 HTML
- Input
属性。下表列出了一些常见的 .NET 类型和生成出的 HTML 类型(并非所有 .NET 类型都在列)。
- type
.NET 类型 | Input 类型 |
---|---|
Bool | type="checkbox" |
String | type="text" |
DateTime | type="datetime" |
Byte | type="number" |
Int | type="number" |
Single, Double | type="number" |
下表列出了 Input Tag Helper 会将其映射到指定 Input 类型的一些常见 特性(并非所有特性都在列)。
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" |
示例:
- 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 >
上述代码生成如下的 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>
和
属性上应用的数据注释在该模型上生成元数据。Input Tag Helper 读取模型元数据并生成
- Password
属性(详见 )。这些属性对验证器进行描述使其附加到 Input 字段上。这提供了 unobtrusive 的 HTML5 和 验证。
- data-val-*
、
- Html.TextBox
、
- Html.TextBoxFor
和
- Html.Editor
有着与 Input Tag Helper 重复的功能。Input Tag Helper 会自动设置
- Html.EditorFor
属性;
- type
和
- Html.TextBox
则不会。
- Html.TextBoxFor
和
- Html.Editor
会处理集合、复杂对象以及模版;Input Tag Helper 则不会。Input Tag Helper 、
- Html.EditorFor
和
- Html.EditorFor
是强类型的(它们使用 lambda 表达式);
- Html.TextBoxFor
和
- Html.TextBox
则不是(它们使用表达式名称)。
- Html.Editor
属性值是一个 同时也是 lambda 表达式右边的部分。因此,你不需要使用
- asp-for
前缀,因为
- Model
在生成的代码中会变成
- asp-for="Property1"
。
- m => m.Property1
- @ {
- var joe = "Joe";
- } < input asp -
- for = "@joe" / >
生成以下代码:
- <input type="text" id="joe" name="joe" value="Joe" />
你还可以通过视图模型的属性路径定位到子属性。考虑这个更复杂的模型,它包含了一个
子属性。
- Address
- 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;
- }
- }
在视图中,我们绑定了
:
- Address.AddressLine1
- @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.AddressLine1" / ><br / ><button type = "submit" > Register < /button>
- </form >
以下 HTML 是根据
生成的:
- Address.AddressLine1
- <input type="text" id="Address_AddressLine1" name="Address.AddressLine1"
- value="" />
示例,包含一个
数组的模型:
- Colors
- public class Person {
- public List < string > Colors {
- get;
- set;
- }
- public int Age {
- get;
- set;
- }
- }
Action 方法:
- public IActionResult Edit(int id, int colorIndex) {
- ViewData["Index"] = colorIndex;
- return View(GetPerson(id));
- }
下面的 Razor 代码展示了如何访问指定的
元素:
- Color
- @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 >
Views/Shared/EditorTemplates/String.cshtml 模版:
- @model string < label asp -
- for = "@Model" > </label>
- <input asp-for="@Model" / > <br / >
使用
的例子:
- List<T>
- public class ToDoItem {
- public string Name {
- get;
- set;
- }
- public bool IsDone {
- get;
- set;
- }
下面的 Razor 代码展示了如何遍历一个集合:
- @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>
- *@/
注意
应始终使用(而 不是
- for
)遍历列表。在 LINQ 表达式中执行索引器会产生开销应当尽量减少。
- foreach
注意
上面示例中被注释的代码演示了应当如何使用操作符代替 lambda 表达式去访问列表中的每一个
- @
。
- ToDoItem
与 Input Tag Helper 类似。
和
- id
属性,以及数据验证属性。
- name
- Html.TextAreaFor
示例:
- 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>/
生成以下代码:
- <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>
相对于纯 HTML label 元素具有以下优势:
特性自动获得描述性的 Label 值。随着时间推移,预期的显示名称可能会变化,而结合使用
- Display
特性与 Label Tag Helper 将会在所有使用它的地方应用
- Display
。
- Display
示例:
- 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 :
- <label>
- <label for="Email">
- Email Address
- </label>
有两种验证 Tag Helper。(用来显示模型上单个属性的验证信息),和 (用来显示验证错误汇总)。 根据模型类的数据注释给 input 元素添加 HTML5 客户端验证属性。验证也在服务端执行。Validation Tag Helper 会在验证发生错误的时候显示这些错误信息。
属性到元素,使验证错误信息附加到指定模型属性的 input 字段上。当客户端验证发生错误,会在
- data-valmsg-for="property"
元素里显示错误信息。
- <span>
- Html.ValidationMessageFor
与 HTML 元素上的
属性一起使用。
- asp-validation-for
- <span asp-validation-for="Email">
- </span>
Validation Message Tag Helper 将生成以下 HTML :
- <span class="field-validation-valid" data-valmsg-for="Email" data-valmsg-replace="true">
- </span>
通常在模型属性相同的
Tag Helper 后面使用 。这样可以在发生验证错误的 input 旁边显示错误信息。
- Input
注意
必须有一个正确引用了 JavaScript 和 脚本的视图进行客户端验证。详见: 。
当服务端验证发生了错误(比如你有自定义的服务端验证或者客户端验证被禁用),MVC 会把错误信息放在
元素的正文中。
- <span>
- <span class="field-validation-error" data-valmsg-for="Email" data-valmsg-replace="true">
- The Email Address field is required.
- </span>
属性的
- asp-validation-summary
元素。
- <div>
。
- @Html.ValidationSummary
用来显示验证信息的摘要。
属性值可以是下面任意一种:
- asp-validation-summary
asp-validation-summary | Validation messages displayed |
---|---|
ValidationSummary.All | Property and model level |
ValidationSummary.ModelOnly | Model |
ValidationSummary.None | None |
在以下示例中,数据模型装饰了
特性,用以在
- DataAnnotation
元素上生成验证错误信息。当发生验证错误的时候, Validation Tag Helper 显示错误信息:
- <input>
- 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 = "ValidationSummary.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 >
生成的 HTML (当模型有效时):
- <form action="/DemoReg/Register" method="post">
- <div class="validation-summary-valid" data-valmsg-summary="true">
- <ul>
- <li style="display:none">
- </li>
- </ul>
- </div>
- 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 e-mail address." data-val="true">
- <br>
- <span class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="Email">
- </span>
- <br>
- Password:
- <input name="Password" id="Password" type="password" data-val-required="The Password field is required."
- data-val="true">
- <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>
的
为 元素指定模型的属性名称,而
- asp-for
则指定 元素。例如:
- asp-items
- <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"
- },
- };
- }
- }
方法初始化
- Index
,设置已选国家然后把它传给
- CountryViewModel
视图。
- Index
- public IActionResult Index() {
- var model = new CountryViewModel();
- model.Country = "CA";
- return View(model);
- }
HTTP POST
方法显示选择的项:
- Index
- [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);
- }
视图:
- 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 (选择了 "CA" ):
- <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>
注意
我们不推荐将或
- ViewBag
用于 Select Tag Helper 。视图模型在提供 MVC 元数据方面更加健壮并且通常来说问题更少。
- ViewData
属性值是一个特例,不需要
- asp-for
前缀,而其他的 Tag Helper 属性则需要(比如
- Model
)。
- asp-items
- <select asp-for="Country" asp-items="Model.Countries">
- </select>
将
属性用于
- enum
并根据
- <select>
的值生成 `selectlistitem] 元素通常是很方便的。
- enum
示例:
- public class CountryEnumViewModel {
- public CountryEnum EnumCountry {
- get;
- set;
- }
- }
- using System.ComponentModel.DataAnnotations;
- namespace FormsTagHelper.ViewModels {
- {
- Mexico,
- [Display(Name = "United States of America")] USA,
- Canada,
- France,
- Germany,
- Spain
- }
- }
方法生产一个 枚举对象.
- @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 >
你可以使用
特性装饰你的枚举数从而获得更丰富的 UI :
- Display
- 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
- }
- }
生成以下的 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">
- 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>
当视图模型包含一个或多个 对象时,会生成 HTML 元素。
把
- CountryViewModelGroup
元素分到 "North America" 和 "Europe" 分组中:
- SelectListItem
- 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 :
- <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>
如果
属性中指定的模型属性是一个
- asp-for
类型, Select Tag Helper 将会自动生成 。例如,已知以下模型:
- IEnumerable
- 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"
- }
- };
- }
- }
使用以下视图:
- @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 >
生成如下 HTML :
- <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>
想要允许无选择,可添加一个 "未选择" 项到选择列表。如果该模型属性是一个 ,则需要使其为可空值 。
- @model CountryViewModel < form asp - controller = "Home"asp - action = "IndexEmpty"method = "post" > <select asp -
- for = "Country"asp - items = "Model.Countries" > <option value = "" > <
- none & gt; < /option>
- </select > <br / ><button type = "submit" > Register < /button>
- </form >
如果你在多个页面里使用 "未选择" 项,可以创建一个模版避免重复的 HTML:
- @model CountryViewModel < form asp - controller = "Home"asp - action = "IndexEmpty"method = "post" > @Html.EditorForModel() < br / ><button type = "submit" > Register < /button>
- </form >
Views/Shared/EditorTemplates/CountryViewModel.cshtml 模版:
- @model CountryViewModel < select asp -
- for = "Country"asp - items = "Model.Countries" > <option value = "" > --none--</option>
- </select >
添加 HTML 元素并不局限于 无选择 的情况。比如,下面的视图和 Action 方法会生成和上面类似的 HTML :
- public IActionResult IndexOption(int id) {
- var model = new CountryViewModel();
- model.Country = "CA";
- return View(model);
- }
- @model CountryViewModel < form asp - controller = "Home"asp - action = "IndexEmpty"method = "post" > <select asp -
- for = "Country" > <option value = "" > <
- none & gt; < /option>
- <option value="MX">Mexico</option > <option value = "CA" > Canada < /option>
- <option value="US">USA</option > </select>
- <br / > <button type = "submit" > Register < /button>
- </form >
元素将会根据当前
- <option>
来源: http://www.cnblogs.com/dotNETCoreSG/p/aspnetcore-4_3_4-working-with-forms.html