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


原文: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

表單 Form 的 Tag Helper:

  • 為 MVC 控制器 Action 或已命名的路由生成 HTML
    action 屬性值。
  • 生成一個隱藏的 請求驗證標記 來防止跨站請求偽裝(當在 HTTP Post 操作方法上應用了 [ValidateAntiForgeryToken] 特性時)。
  • 提供 asp-route-<參數名> 屬性, <參數名> 是路由里面添加過的值。 Html.BeginFormHtml.BeginRouteFormrouteValues 參數提供了類似的功能。
  • 有 HTML Helper 替代方法 Html.BeginFormHtml.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-controllerasp-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 屬性中指定的表達式名稱生成 idname 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 類型
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>

EmailPassword 屬性上應用的數據注釋在該模型上生成元數據。Input Tag Helper讀取模型元數據並生成 HTML5 data-val-* 屬性(詳見 Model Validation)。這些屬性對驗證器進行描述使其附加到 Input 字段上。這提供了 unobtrusive 的 HTML5 和 jQuery 驗證。

替代 Input Tag Helper 的 Html Helper

Html.TextBoxHtml.TextBoxForHtml.EditorHtml.EditorFor 有着與 Input Tag Helper 重復的功能。Input Tag Helper 會自動設置 type 屬性;Html.TextBoxHtml.TextBoxFor 則不會。Html.EditorHtml.EditorFor 會處理集合、復雜對象以及模版;Input Tag Helper 則不會。Input Tag Helper 、Html.EditorForHtml.TextBoxFor 是強類型的(它們使用 lambda 表達式);Html.TextBoxHtml.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> 元素生成 idname 屬性,以及數據驗證屬性。
  • 提供強類型。
  • 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 &#x27;1024&#x27;."
   data-val-maxlength-max="1024"
   data-val-minlength="The field Description must be a string or array type with a minimum length of &#x27;5&#x27;."
   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生成一致的 idfor 元素,因此它們可以正確地關聯起來。本例中的標簽文本來自於 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 和關聯到你的模型屬性的 option 元素。

Select Tag Helperasp-forselect 元素指定模型的屬性名稱,而 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>

注意
我們不推薦將 ViewBagViewData 用於 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> 元素。

CountryViewModelGroupSelectListItem 元素分到 "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="">&lt;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 <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="">&lt;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> 元素將會根據當前的 Country 值被正確選中(加上 selected="selected" 屬性)。

 <form method="post" action="/Home/IndexEmpty">
     <select id="Country" name="Country">
         <option value="">&lt;none&gt;</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>

其他資源

返回目錄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM