ASP.NET Core 中文文档 第四章 MVC(3.4)如何使用表单
原文:Working with Forms
作者:Rick Anderson、Dave Paquette、Jerrie 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
andHtml.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 类型 |
---|---|
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>
Email
和 Password
属性上应用的数据注释在该模型上生成元数据。Input Tag Helper读取模型元数据并生成 HTML5 data-val-*
属性(详见 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-summary | Validation messages displayed |
---|---|
ValidationSummary.All | Property and model level |
ValidationSummary.ModelOnly | Model |
ValidationSummary.None | None |
示例
在以下示例中,数据模型装饰了 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 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>
其他资源
ASP.NET Core 中文文档 第四章 MVC(3.4)如何使用表单的更多相关文章
- ASP.NET Core 中文文档 第四章 MVC(4.2)控制器操作的路由
原文:Routing to Controller Actions 作者:Ryan Nowak.Rick Anderson 翻译:娄宇(Lyrics) 校对:何镇汐.姚阿勇(Dr.Yao) ASP.NE ...
- ASP.NET Core 中文文档 第四章 MVC(3.6.1 )Tag Helpers 介绍
原文:Introduction to Tag Helpers 作者:Rick Anderson 翻译:刘浩杨 校对:高嵩(Jack) 什么是 Tag Helpers? Tag Helpers 提供了什 ...
- ASP.NET Core 中文文档 第四章 MVC(3.8)视图中的依赖注入
原文:Dependency injection into views 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:孟帅洋(书缘) ASP.NET Core 支持在视图中使用 依赖 ...
- ASP.NET Core 中文文档 第四章 MVC(4.6)Areas(区域)
原文:Areas 作者:Dhananjay Kumar 和 Rick Anderson 翻译:耿晓亮(Blue) 校对:许登洋(Seay) Areas 是 ASP.NET MVC 用来将相关功能组织成 ...
- ASP.NET Core 中文文档 第四章 MVC(4.5)测试控制器逻辑
原文: Testing Controller Logic 作者: Steve Smith 翻译: 姚阿勇(Dr.Yao) 校对: 高嵩(Jack) ASP.NET MVC 应用程序的控制器应当小巧并专 ...
- ASP.NET Core 中文文档 第四章 MVC(4.4)依赖注入和控制器
原文: Dependency Injection and Controllers 作者: Steve Smith 翻译: 刘浩杨 校对: 孟帅洋(书缘) ASP.NET Core MVC 控制器应通过 ...
- ASP.NET Core 中文文档 第四章 MVC(4.1)Controllers, Actions 和 Action Results
原文:Controllers, Actions, and Action Results 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:许登洋(Seay) Action 和 acti ...
- ASP.NET Core 中文文档 第四章 MVC(3.9)视图组件
作者: Rick Anderson 翻译: 娄宇(Lyrics) 校对: 高嵩 章节: 介绍视图组件 创建视图组件 调用视图组件 演练:创建一个简单的视图组件 附加的资源 查看或下载示例代码 介绍视图 ...
- ASP.NET Core 中文文档 第四章 MVC(3.7 )局部视图(partial)
原文:Partial Views 作者:Steve Smith 翻译:张海龙(jiechen).刘怡(AlexLEWIS) 校对:许登洋(Seay).何镇汐.魏美娟(初见) ASP.NET Core ...
- ASP.NET Core 中文文档 第四章 MVC(01)ASP.NET Core MVC 概览
原文:Overview of ASP.NET Core MVC 作者:Steve Smith 翻译:张海龙(jiechen) 校对:高嵩 ASP.NET Core MVC 是使用模型-视图-控制器(M ...
随机推荐
- 透过WinDBG的视角看String
摘要 : 最近在博客园里面看到有人在讨论 C# String的一些特性. 大部分情况下是从CODING的角度来讨论String. 本人觉得非常好奇, 在运行时态, String是如何与这些特性联系上的 ...
- 一百元的智能家居——Asp.Net Mvc Api+讯飞语音+Android+Arduino
大半夜的,先说些废话提提神 如今智能家居已经不再停留在概念阶段,高大上的科技公司都已经推出了自己的部分或全套的智能家居解决方案,不过就目前的现状而言,大多还停留在展厅阶段,还没有广泛的推广起来,有人说 ...
- JAVA语言中的修饰符
JAVA语言中的修饰符 -----------------------------------------------01--------------------------------------- ...
- History API与浏览器历史堆栈管理
移动端开发在某些场景中有着特殊需求,如为了提高用户体验和加快响应速度,常常在部分工程采用SPA架构.传统的单页应用基于url的hash值进行路由,这种实现不存在兼容性问题,但是缺点也有--针对不支持o ...
- php注册审核
通过注册审核,判断刚创建的账户是否可以使用. 后台管理员审核通过后,账号可以使用. 通过session 设置只能通过登录入口进入网页. 原理:通过数据库设置账号的一个字段状态,例: isok:1, i ...
- JavaWeb——Listener
一.基本概念 JavaWeb里面的listener是通过观察者设计模式进行实现的.对于观察者模式,这里不做过多介绍,大概讲一下什么意思. 观察者模式又叫发布订阅模式或者监听器模式.在该模式中有两个角色 ...
- jdb调试scala代码的简单介绍
在linux调试C/C++的代码需要通过gdb,调试java代码呢?那就需要用到jdb工具了.关于jdb的用法在网上大家都可以找到相应的文章,但是对scala进行调试的就比较少了.其实调试的大致流程都 ...
- java中Action层、Service层和Dao层的功能区分
Action/Service/DAO简介: Action是管理业务(Service)调度和管理跳转的. Service是管理具体的功能的. Action只负责管理,而Service负责实施. DAO只 ...
- PhpStorm和WAMP配置调试参数,问题描述Error. Interpreter is not specified or invalid. Press “Fix” to edit your project configuration.
PhpStorm和WAMP配置调试参数 问题描述: Error. Interpreter is not specified or invalid. Press “Fix” to edit your p ...
- 真正的汉化-PowerDesigner 16.5 汉化
一.背景 经常使用PowerDesigner,之前使用15版本,后来16出来后,就一直在使用16,不过一直是英文.一些同事对使用英文版总显示有些吃力. 遍寻百度.必应,都没有找到真正的针对版本16的汉 ...