您的位置:首页 > 编程语言 > ASP

ASP.NET Core 中文文档 第四章 MVC(3.4)如何使用表单

2016-09-12 08:23 1136 查看
原文:Working with Forms

作者:Rick AndersonDave PaquetteJerrie Pelser

翻译:姚阿勇(Dr.Yao)

校对:孟帅洋(书缘)

这篇文章演示了如何使用表单以及表单中常用的 HTML 元素。HTML 的 Form 元素提供了 Web 应用向服务器回发数据的主要机制。本文的大部分在描述 Tag Helpers 以及它们如何能帮你有效地构建健壮的表单。在阅读本文之前,我们建议你阅读一下 Tag Helpers

在很多情况下,HTML Helpers 都提供了对某个 Tag Helper 的替代方法,但重要的是必须意识到 Tag Helper 不是要取代 HTML Helper,而且也并不是每个 HTML Helper 都有对应的 Tag Helper。当一个 HTML Helper 作为替代方案存在时,是有意为之的。

章节:

Form Tag Helper

Input Tag Helper

Textarea Tag Helper

Textarea Tag Helper

Label Tag Helper

验证Tag Helper

Select Tag Helper

其他资源

Form Tag Helper

表单 Form 的 Tag Helper:

为 MVC 控制器 Action 或已命名的路由生成 HTML
action
属性值。

生成一个隐藏的 请求验证标记 来防止跨站请求伪装(当在 HTTP Post 操作方法上应用了
[ValidateAntiForgeryToken]
特性时)。

提供
asp-route-<参数名>
属性,
<参数名>
是路由里面添加过的值。
Html.BeginForm
Html.BeginRouteForm
routeValues
参数提供了类似的功能。

有 HTML Helper 替代方法
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
生成
action
属性值。Form Tag Helper 也会生成一个隐藏的 请求验证标记 来防止跨站请求伪装(当在HTTP Post 方法上应用了
[ValidateAntiForgeryToken]
特性时)。要保护纯 HTML 避免跨站请求伪装是非常困难的,Form Tag Helper 为你提供了这个服务。

使用命名路由

Tag Helper 属性
asp-route
也能为 HTML
action
属性生成标记。一个应用含有名为
register
路由 可以在注册页面使用如下标记:

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

Views/Account 文件夹下的很多视图(在你创建一个带有 个人用户账户 的新 Web 应用时生成的)都含有 asp-route-returnurl 属性:

<form asp-controller="Account" asp-action="Login"
asp-route-returnurl="@ViewData["ReturnUrl"]"
method="post" class="form-horizontal" role="form">


注意

采用内建的模版,只有在你尚未经过验证或授权的情况下去尝试访问需授权的资源时,
returnUrl
才会被自动填入。当你尝试一个未授权的访问,安全中间件会根据
returnUrl
的设置将你重定向到登录页面。


Input Tag Helper

Input Tag Helper将 HTML
<input>
元素绑定到 Razor 视图中的模型表达式上。

语法:

<input asp-for="<Expression Name>" />

Input Tag Helper:

asp-for
属性中指定的表达式名称生成
id
name
HTML 属性。
asp-for="Property1.Property2"
等价于
m => m.Property1.Property2
,就是说属性值实际上是表达式的一部分。
asp-for
属性值所使用的就是表达式的名称。

基于模型类型和应用在模型属性上的 数据注释 特性来设置 HTML
type
的属性值。

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

根据应用在模型属性上的 数据注释 特性生成 HTML5 验证属性。

与 HTML Helper
Html.TextBoxFor
and
Html.EditorFor
功能重叠。详情可参见 Input Tag Helper 的 HTML Helper 替代方法 一节。

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基于 .NET 类型来设置 HTML
type
属性。下表列出了一些常见的 .NET 类型和生成出的 HTML 类型(并非所有 .NET 类型都在列)。

.NET 类型Input 类型
Booltype="checkbox"
Stringtype="text"
DateTimetype="datetime"
Bytetype="number"
Inttype="number"
Single, Doubletype="number"
下表列出了 Input Tag Helper会将其映射到指定 Input 类型的一些常见 数据注释 特性(并非所有特性都在列)。

AttributeInput Type
[EmailAddress]type="email"
[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>

Email
Password
属性上应用的数据注释在该模型上生成元数据。Input Tag Helper读取模型元数据并生成 HTML5" target=_blank>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>

Email
Password
属性上应用的数据注释在该模型上生成元数据。Input Tag Helper读取模型元数据并生成 [url=https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5]HTML5
data-val-*
属性(详见 [url=https://docs.asp.net/en/latest/mvc/models/validation.html]Model Validation)。这些属性对验证器进行描述使其附加到 Input 字段上。这提供了 unobtrusive 的 HTML5 和 jQuery 验证。

替代 Input Tag Helper 的 Html Helper

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
是强类型的(它们使用 lambda 表达式);
Html.TextBox
Html.Editor
则不是(它们使用表达式名称)。

表达式名称

asp-for
属性值是一个 ModelExpression 同时也是 lambda 表达式右边的部分。因此,你不需要使用
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
(而 不是
foreach
)遍历列表。在 LINQ 表达式中执行索引器会产生开销应当尽量减少。




注意

上面示例中被注释的代码演示了应当如何使用
@
操作符代替 lambda 表达式去访问列表中的每一个
ToDoItem



Textarea Tag Helper

Textarea Tag Helper 与 Input Tag Helper类似。

<textarea>
元素生成
id
name
属性,以及数据验证属性。

提供强类型。

HTML Helper 替代选项:
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>

Label Tag Helper

根据表达式名称在
<label>
元素上生成标签文字和
for
属性。

HTML Helper 替代选项:
Html.LabelFor


Label Tag Helper 相对于纯 HTML label 元素具有以下优势:

可从
Display
特性自动获得描述性的 Label 值。随着时间推移,预期的显示名称可能会变化,而结合使用
Display
特性与 Label Tag Helper将会在所有使用它的地方应用
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>

以下是为
<label>
元素生成的 HTML :

<label for="Email">Email Address</label>

Label Tag Helper生成了 "Email" 的
for
属性值,也就是与
<input>
元素关联的 ID 。Tag Helper生成一致的
id
for
元素,因此它们可以正确地关联起来。本例中的标签文本来自于
Display
特性。如果模型没有
Display
特性,标签文本则会是表达式的属性名称。

验证 Tag Helper

有两种验证Tag Helper。Validation Message Tag Helper(用来显示模型上单个属性的验证信息),和 Validation Summary Tag Helper (用来显示验证错误汇总)。Input Tag Helper 根据模型类的数据注释给 input 元素添加 HTML5 客户端验证属性。验证也在服务端执行。Validation Tag Helper会在验证发生错误的时候显示这些错误信息。

Validaton Message Tag Helper

添加 HTML5
data-valmsg-for="property"
属性到 span 元素,使验证错误信息附加到指定模型属性的 input 字段上。当客户端验证发生错误,jQuery 会在
<span>
元素里显示错误信息。

验证也发生在服务端。客户端可能会禁用 JavaScript 那么验证就只能在服务端完成。

HTML Helper 替代选项:
Html.ValidationMessageFor


Validaton Message Tag Helper 与 HTML span 元素上的
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>

通常在模型属性相同的
Input
Tag Helper后面使用 Validation Message Tag Helper 。这样可以在发生验证错误的 input 旁边显示错误信息。


注意

必须有一个正确引用了 JavaScript 和 jQuery 脚本的视图进行客户端验证。详见: Model Validation


当服务端验证发生了错误(比如你有自定义的服务端验证或者客户端验证被禁用),MVC 会把错误信息放在
<span>
元素的正文中。

<span class="field-validation-error" data-valmsg-for="Email"
data-valmsg-replace="true">
The Email Address field is required.
</span>

验证摘要Tag Helper

选取带有
asp-validation-summary
属性的
<div>
元素。

HTML Helper 替代选项:
@Html.ValidationSummary


Validation Summary Tag Helper 用来显示验证信息的摘要。
asp-validation-summary
属性值可以是下面任意一种:

asp-validation-summaryValidation messages displayed
ValidationSummary.AllProperty and model level
ValidationSummary.ModelOnlyModel
ValidationSummary.NoneNone

示例

在以下示例中,数据模型装饰了
DataAnnotation
特性,用以在
<input>
元素上生成验证错误信息。当发生验证错误的时候, Validation Tag Helper显示错误信息:

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>

Select Tag Helper

生成 select 和关联到你的模型属性的 option 元素。

Select Tag Helper
asp-for
select 元素指定模型的属性名称,而
asp-items
则指定 option 元素。例如:

<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
ViewData
用于 Select Tag Helper 。视图模型在提供 MVC 元数据方面更加健壮并且通常来说问题更少。


asp-for
属性值是一个特例,不需要
Model
前缀,而其他的 Tag Helper 属性则需要(比如
asp-items
)。

<select asp-for="Country" asp-items="Model.Countries"></select>

枚举绑定

enum
属性用于
<select>
并根据
enum
的值生成 `SelectListItemselectlistitem] 元素通常是很方便的。

示例:

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

GetEnumSelectList 方法生产一个 SelectList 枚举对象.

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

你可以使用
Display
特性装饰你的枚举数从而获得更丰富的 UI :

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>

选项分组

当视图模型包含一个或多个 SelectListGroup 对象时,会生成 HTML
<optgroup>
元素。

CountryViewModelGroup
SelectListItem
元素分到 "North America" 和 "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 :

<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
属性中指定的模型属性是一个
IEnumerable
类型, Select Tag Helper 将会自动生成 multiple = "multiple"。例如,已知以下模型:

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>

无选择

想要允许无选择,可添加一个 “未选择” 项到选择列表。如果该模型属性是一个 值类型,则需要使其为可空值 nullable

@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">
<select asp-for="Country" asp-items="Model.Countries">
<option value=""><none></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
<option>
元素并不局限于 无选择 的情况。比如,下面的视图和 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></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>
元素将会根据当前的
Country
值被正确选中(加上
selected="selected"
属性)。

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

其他资源

Tag Helpers

HTML Form 元素

请求验证标记

Model Binding

Model Validation

数据注释

本文的示例代码

返回目录
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: