ASP.NET Core のフォームのタグ ヘルパー

作成者: Rick AndersonN. Taylor MullenDave PaquetteJerrie Pelser

このドキュメントでは、フォームとフォームでよく使用される HTML 要素の使用方法について説明します。 HTML の Form 要素には、Web アプリケーションからサーバーにデータをポスト バックするために使用する主要なメカニズムがあります。 このドキュメントでは、タグ ヘルパーと、タグ ヘルパーを利用して堅牢な HTML フォームを生産的に作成する方法について主に説明します。 このドキュメントを読む前に、タグ ヘルパーの概要に関するページを読むことをお勧めします。

多くの場合、HTML ヘルパーは、特定のタグ ヘルパーに代わる方法を提供します。 ただし、タグ ヘルパーは HTML ヘルパーを置き換えるのではなく、各 HTML ヘルパーにはタグ ヘルパーがないことを認識することが重要です。 HTML ヘルパーの代替が存在する場合は記載します。

フォーム タグ ヘルパー

フォーム タグ ヘルパー:

  • MVC コントローラー アクションまたは名前付きルートの HTML <FORM>action 属性値を生成します。

  • 非表示の 要求検証トークン を生成してクロスサイトリクエストフォージェリを防止します (HTTP Post アクション メソッドで [ValidateAntiForgeryToken] 属性と共に使用する場合)。

  • asp-route-<Parameter Name> 属性を提供します (<Parameter Name> がルート値に追加される場合)。 routeValues および Html.BeginFormHtml.BeginRouteForm パラメーターを指定すると、同様の機能が提供されます。

  • HTML ヘルパーの代替 Html.BeginFormHtml.BeginRouteFormがあります。

サンプル:

<form asp-controller="Demo" asp-action="Register" method="post">
    <!-- Input and Submit elements -->
</form>

前のフォーム タグ ヘルパーでは、次の HTML が生成されます。

<form method="post" action="/Demo/Register">
    <!-- Input and Submit elements -->
    <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

MVC ランタイムで、フォーム タグ ヘルパーの属性 actionasp-controller から asp-action 属性値が生成されます。 また、フォーム タグ ヘルパーも、クロスサイト リクエスト フォージェリを防ぐために、非表示の要求検証トークンを生成します (HTTP POST アクション メソッドで [ValidateAntiForgeryToken] 属性と共に使用する場合)。 クロスサイト リクエスト フォージェリから純粋な HTML フォームを保護することは困難ですが、フォーム タグ ヘルパーによってこのサービスが提供されます。

名前付きのルートの使用

asp-route タグ ヘルパー属性で、HTML action 属性のマークアップを生成することもできます。 ルートに名前registerが付けられたアプリは、登録ページに以下のマークアップを使用できます:

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

ビュー/アカウント フォルダー内のビューの多くは (個々のアカウントで新しい 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 が設定されたログイン ページにリダイレクトされます。

フォーム アクション タグ ヘルパー

フォーム アクション タグ ヘルパーにより、生成されたformaction または <button ...> タグ上に <input type="image" ...> 属性が生成されます。 formaction 属性では、フォームがそのデータを送信する場所を制御します。 これは、型 < のimage要素と<ボタン>要素をバインドします。 フォーム アクション タグ ヘルパーにより、AnchorTagHelperasp- 属性を複数使うことが可能になり、対応する要素に向けて何の formaction リンクが生成されるかを制御できます。

AnchorTagHelper の値を制御するためにサポートされている formaction 属性:

属性 説明
asp-controller コントローラーの名前。
asp-action アクション メソッドの名前です。
asp-area 領域の名前です。
asp-page Razor ページの名前。
asp-page-handler Razor ページ ハンドラーの名前。
asp-route ルートの名前。
asp-route-{value} 単一の URL ルート値です。 たとえば、「 asp-route-id="1234" 」のように入力します。
asp-all-route-data すべてのルート値です。
asp-fragment URL フラグメントです。

コントローラーに送信する例

次のマークアップは、入力またはボタンが選択されたときに、フォームを IndexHomeController アクションに送信します。

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

以前のマークアップでは次の HTML が生成されます。

<form method="post">
    <button formaction="/Home">Click Me</button>
    <input type="image" src="..." alt="Or Click Me" formaction="/Home">
</form>

ページに送信する例

次のマークアップでは、AboutRazor Pages にフォームを送信します:

<form method="post">
    <button asp-page="About">Click Me</button>
    <input type="image" src="..." alt="Or Click Me" asp-page="About">
</form>

以前のマークアップでは次の HTML が生成されます。

<form method="post">
    <button formaction="/About">Click Me</button>
    <input type="image" src="..." alt="Or Click Me" formaction="/About">
</form>

ルート例に送信する

/Home/Test エンドポイントを検討します。

public class HomeController : Controller
{
    [Route("/Home/Test", Name = "Custom")]
    public string Test()
    {
        return "This is the test page";
    }
}

次のマークアップでは、/Home/Test エンドポイントにフォームを送信します。

<form method="post">
    <button asp-route="Custom">Click Me</button>
    <input type="image" src="..." alt="Or Click Me" asp-route="Custom">
</form>

以前のマークアップでは次の HTML が生成されます。

<form method="post">
    <button formaction="/Home/Test">Click Me</button>
    <input type="image" src="..." alt="Or Click Me" formaction="/Home/Test">
</form>

入力タグ ヘルパー

入力タグ ヘルパーは、HTML <input> 要素を Razor ビューのモデル式にバインドします。

構文:

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

入力タグヘルパー

  • id 属性で指定された式の名前の name および asp-for HTML 属性を生成します。 asp-for="Property1.Property2"m => m.Property1.Property2 と等価です。 式の名前は、asp-for 属性値に使用されるものです。 詳細については、「 式名 」セクションを参照してください。

  • モデルの種類とモデル プロパティに適用されるtype属性に基づいて、HTML 属性値を設定します。

  • 指定した場合、HTML type 属性値は上書きされません。

  • モデル プロパティに適用されたデータ注釈属性から HTML5 検証属性を生成します。

  • Html.TextBoxFor および Html.EditorFor と重複する HTML ヘルパー機能があります。 詳細については、「入力タグ ヘルパーの代替となる HTML ヘルパー」セクションを参照してください。

  • 厳密な型指定を提供します。 プロパティの名前が変更され、タグ ヘルパーを更新しない場合は、次のようなエラーが表示されます。

    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 タグ ヘルパーは、.NET 型に基づいて HTML type 属性を設定します。 次の表は、一般的な.NET 型と生成される HTML 型の一部をまとめたものです (すべての .NET 型を網羅した一覧ではありません)。

.NET 型 入力タイプ
Bool type="checkbox"
type="text"
日付と時間 type="datetime-local"
Byte type="number"
int type="number"
シングル、ダブル type="number"

次の表は、入力タグ ヘルパーが特定の入力型にマップする一般的な データ注釈 属性を示しています (すべての検証属性が一覧表示されているわけではありません)。

属性 入力タイプ
[メールアドレス] type="Eメール"
[Url] type="url"
[HiddenInput] type="hidden"
電話 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">
    <label>Email: <input asp-for="Email" /></label> <br />
    <label>Password: <input asp-for="Password" /></label><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 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>

Email および Password プロパティに適用されたデータ注釈によって、モデルに関するメタデータが生成されます。 入力タグ ヘルパーはモデルのメタデータを使用し、HTML5data-val-* 属性を生成します (モデルの検証に関するページを参照してください)。 これらの属性に、入力フィールドにアタッチする検証コントロールを記述します。 これで、控えめな HTML5 と jQuery の検証機能を提供します。 目立たない属性には data-val-rule="Error Message"形式があります。ここで、rule は検証規則の名前 ( data-val-requireddata-val-emaildata-val-maxlengthなど) です。 属性にエラー メッセージが指定されている場合は、 data-val-rule 属性の値として表示されます。 data-val-ruleName-argumentName="argumentValue" など、ルールに関する追加の詳細情報を提供するフォームの属性 data-val-maxlength-max="1024" もあります。

複数の input コントロールを同じプロパティにバインドすると、生成されたコントロールは同じ id を共有するため、生成されたマークアップは無効になります。 重複を防ぐには、各コントロールの id 属性を明示的に指定します。

チェックボックスの非表示入力のレンダリング

HTML5 のチェックボックスでは、オフになったときに値を送信しません。 オフになったチェックボックスについて既定値を送信できるようにするために、入力タグ ヘルパーによって、チェックボックスの追加の非表示入力が生成されます。

たとえば、Razor ブール型モデル プロパティに入力タグヘルパーを使用する次の IsChecked マークアップについて考えてみます。

<form method="post">
    <input asp-for="@Model.IsChecked" />
    <button type="submit">Submit</button>
</form>

上記の Razor マークアップでは、次のような HTML マークアップが生成されます。

<form method="post">
    <input name="IsChecked" type="checkbox" value="true" />
    <button type="submit">Submit</button>

    <input name="IsChecked" type="hidden" value="false" /> 
</form>

上記の HTML マークアップには、IsChecked という名前の追加の非表示入力と、false の値が表示されます。 既定では、この非表示入力はフォームの最後に表示されます。 フォームが送信されたとき、次のようになります。

  • IsChecked チェックボックスの入力をオンにすると、truefalse の両方が値として送信されます。
  • IsChecked チェックボックスの入力をオフにすると、非表示の入力値 false のみが送信されます。

ASP.NET Core モデルバインド プロセスは、bool 値にバインドするときに最初の値のみを読み取ります。これにより、チェックボックスがオンの場合は true になり、チェックボックスがオフの場合は false になります。

非表示入力の表示の動作を構成するには、CheckBoxHiddenInputRenderModeMvcViewOptions.HtmlHelperOptions プロパティを設定します。 次に例を示します。

services.Configure<MvcViewOptions>(options =>
    options.HtmlHelperOptions.CheckBoxHiddenInputRenderMode =
        CheckBoxHiddenInputRenderMode.None);

上記のコードでは、CheckBoxHiddenInputRenderModeCheckBoxHiddenInputRenderMode.None に設定することにより、チェックボックスの非表示入力の表示を無効にします。 使用可能なすべての表示モードについては、CheckBoxHiddenInputRenderMode 列挙型を参照してください。

入力タグ ヘルパーの代替となる HTML ヘルパー

Html.TextBoxHtml.TextBoxForHtml.Editor、および Html.EditorFor には、入力タグ ヘルパーと重複する機能があります。 入力タグ ヘルパーでは type 属性が自動的に設定されますが、Html.TextBoxHtml.TextBoxFor では自動設定されません。 Html.EditorHtml.EditorFor はコレクション、複雑なオブジェクト、およびテンプレートを処理します。入力タグ ヘルパーは処理しません。 入力タグ ヘルパー、 Html.EditorFor、および Html.TextBoxFor は厳密に型指定されます (ラムダ式を使用します)。 Html.TextBox および Html.Editor は使用されません (式名を使用します)。

HTML属性

@Html.Editor()@Html.EditorFor() は、既定のテンプレートを実行するときに ViewDataDictionary という名前の特殊な htmlAttributes エントリを使用します。 この動作は、必要に応じて additionalViewData パラメーターを使用して拡張されます。 キー "htmlAttributes" は大文字と小文字を区別しません。 キー "htmlAttributes" は、htmlAttributes のような入力ヘルパーに渡される @Html.TextBox() オブジェクトと同様に処理されます。

@Html.EditorFor(model => model.YourProperty, 
  new { htmlAttributes = new { @class="myCssClass", style="Width:100px" } })

式の名前

asp-for 属性値は ModelExpression であり、ラムダ式の右辺です。 そのため、 asp-for="Property1" は生成されたコードで m => m.Property1 になるため、 Modelでプレフィックスを付ける必要はありません。 "@" 文字を使用してインライン式を開始し、m. の前に移動できます。

@{
  var joe = "Joe";
}

<input asp-for="@joe">

以下が生成されます。

<input type="text" id="joe" name="joe" value="Joe">

asp-for="CollectionProperty[23].Member" の値が asp-for="CollectionProperty[i].Member" の場合、i はコレクションのプロパティを使用して、23 と同じ名前を生成します。

ASP.NET Core MVC で ModelExpression の値が計算されるとき、ModelState を含む、いくつかのソースが検査されます。 <input type="text" asp-for="Name"> を検討します。 計算された value 属性は、次のうちの最初の非 null 値です。

  • キー "Name" を持つ ModelState エントリ。
  • Model.Name の結果。

ビュー モデルのプロパティ パスを使用して、子プロパティに移動することもできます。 子 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">
    <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>

Address.AddressLine1 に対して次の HTML が生成されます。

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

アクション メソッド:

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>

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>

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

値を foreach または asp-for と同じコンテキストで使用する場合は、可能であれば Html.DisplayFor を使用する必要があります。 一般に、反復子を割り当てる必要がないため、(使用可能なシナリオでは) for の方が foreach よりも優れています。ただし、LINQ 式内でのインデクサーの評価はコストが高くなる可能性があるため、最小限に抑える必要があります。

 

上記のコメント付きサンプル コードは、ラムダ式を @ 演算子に置き換えて、リスト内の各 ToDoItem にアクセスする方法を示しています。

Textarea タグ ヘルパー

Textarea Tag Helper タグ ヘルパーは、Input タグ ヘルパーと似ています。

  • モデルから id および name 属性を生成し、<textarea> 要素用のデータ検証属性も生成します。

  • 厳密な型指定を提供します。

  • HTML ヘルパーの代替: 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>

次の HTML が生成されます。

<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要素にラベルキャプションと属性を生成します。

  • HTML ヘルパーの代替: Html.LabelFor

Label Tag Helper は、純粋な HTML の label 要素よりも次の点で優れています:

  • Display 属性からわかりやすいラベル値が自動的に取得されます。 意図した表示名は時間と共に変化する可能性があります。また、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>

<label> 要素に対して次の HTML が生成されます。

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

ラベル タグ ヘルパーから "Email" の属性値 for が生成されました。これは、<input> に関連付けられた ID です。 タグ ヘルパーでは一貫性のある id および for 要素が生成されるので、正しく関連付けられます。 このサンプルのキャプションは Display 属性に由来します。 モデルに Display 属性を含めなかった場合、キャプションは式のプロパティ名になります。 既定のキャプションをオーバーライドするには、ラベル タグ内にキャプションを追加します。

検証タグヘルパー

2 つの検証タグ ヘルパーがあります。 Validation Message Tag Helper (モデルの単一のプロパティに関する検証メッセージを表示する) と Validation Summary Tag Helper (検証エラーの概要を表示する) です。 Input Tag Helper は、モデル クラスのデータ注釈属性に基づいて、HTML5 のクライアント側検証属性を input 要素に追加します。 検証はサーバー側でも実行されます。 検証エラーが発生すると、検証タグ ヘルパーによってこれらのエラー メッセージが表示されます。

検証メッセージ タグ ヘルパー

  • HTML5data-valmsg-for="property" 属性を span 要素に追加します。これによって、指定されたモデル プロパティの入力フィールドに検証エラー メッセージがアタッチされます。 クライアント側の検証エラーが発生すると、jQuery によって <span> 要素のエラー メッセージが表示されます。

  • 検証はサーバー側でも実行されます。 クライアントで JavaScript が無効になっている可能性があり、一部の検証はサーバー側でのみ実行できます。

  • HTML ヘルパーの代替: Html.ValidationMessageFor

Validation Message Tag Helper は、HTML の asp-validation-for 要素で 属性と共に使用されます。

<span asp-validation-for="Email"></span>

検証メッセージ タグ ヘルパーから、次の HTML が生成されます。

<span class="field-validation-valid"
  data-valmsg-for="Email"
  data-valmsg-replace="true"></span>

一般的に、同じプロパティの場合は、Validation Message Tag Helper タグ ヘルパーの後に Input を使用します。 こうすることで、エラーの原因となった入力の近くで検証エラー メッセージが表示されます。

クライアント側の検証のために、正しい JavaScript および jQuery のスクリプト参照を使用したビューを用意する必要があります。 詳細については、「モデルの 検証」を参照してください。

サーバー側の検証エラーが発生した場合 (カスタムのサーバー側の検証がある場合や、クライアント側の検証が無効な場合など)、MVC はそのエラー メッセージを <span> 要素の本文として配置します。

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

検証概要タグ ヘルパー

  • <div>要素でasp-validation-summary属性を対象とします。

  • HTML ヘルパーの代替: @Html.ValidationSummary

Validation Summary Tag Helper は、検証メッセージの概要を表示するために使用されます。 asp-validation-summary 属性値には、次のいずれかを指定できます。

ASP検証サマリー 検証メッセージが表示されます
All プロパティとモデル レベル
ModelOnly モデル
None なし

サンプル

次の例のデータ モデルは、DataAnnotation 属性が設定されており、<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="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 (モデルが有効な場合):

<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 要素と、関連する option 要素を生成します。

  • HTML ヘルパーの代替 Html.DropDownListForHtml.ListBoxForがあります。

Select Tag Helper asp-forselect 要素のモデル プロパティ名を指定し、asp-itemsoption 要素を指定します。 次に例を示します。

<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 を使用することはお勧めしません。 ビュー モデルは、MVC メタデータを提供する際の堅牢性が高く、問題が少なくなります。

asp-for属性値は特殊なケースであり、Model プレフィックスは必要ありません。 その他のタグ ヘルパー属性 ( asp-items など) が行います。

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

Enum バインディング

<select>enum プロパティと組み合わせて使用し、SelectListItem 値から enum 要素を生成すると便利な場合がよくあります。

サンプル:

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

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>

より高機能な 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 の <optgroup> 要素は、ビュー モデルに 1 つ以上の SelectListGroup オブジェクトが含まれている場合に生成されます。

CountryViewModelGroupSelectListItem 要素を "北米" グループと "ヨーロッパ" グループに分けます。

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

2 つのグループを次に示します。

オプション グループの例

生成される 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 タグ ヘルパーは 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>

選択なし

複数のページで "未指定" オプションを使用しているとわかった場合は、テンプレートを作成して 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> 要素の追加は、"選択なし" の場合に限定されません。 たとえば、次のビューおよびアクション メソッドでは、前のコードと同様の HTML が生成されます。

public IActionResult IndexNone()
{
    var model = new CountryViewModel();
    model.Countries.Insert(0, new SelectListItem("<none>", ""));
    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>値に応じて、適切なselected="selected"要素が選択されます (Country属性が含まれます)。

public IActionResult IndexOption(int id)
{
    var model = new CountryViewModel();
    model.Country = "CA";
    return View(model);
}
 <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>

その他のリソース