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> がルート値に追加される場合)。 Html.BeginForm および Html.BeginRouteFormrouteValues パラメーターを指定すると、同様の機能が提供されます。

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

名前付きのルートの使用

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

Note

承認済みで認証されていないリソースまたは承認されていないリソースにアクセスしようとすると、組み込みのテンプレートを使用して、returnUrl のみが自動的に設定されます。 未承認のアクセスを試行すると、セキュリティ ミドルウェアによって、returnUrl が設定されたログイン ページにリダイレクトされます。

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

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

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

属性 説明
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 フラグメントです。

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

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

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

入力タグ ヘルパー

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

構文:

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

入力タグ ヘルパー:

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

  • モデル プロパティに適用されているモデル型とデータ注釈に基づいて HTML の type 属性値を設定します

  • 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"
String type="text"
DateTime type="datetime-local"
Byte type="number"
int type="number"
Single、Double type="number"

次の表は、入力タグ ヘルパーが特定の入力の型にマップする一般的なデータ注釈属性の一部をまとめたものです (すべての検証属性を網羅した一覧ではありません)。

属性 入力タイプ
[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 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-maxlength-max="1024" など、ルールに関する追加の詳細情報を提供するフォームの属性 data-val-ruleName-argumentName="argumentValue" もあります。

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

チェックボックスの非表示入力の表示

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

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

<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 になります。

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

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

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

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

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

HtmlAttributes

@Html.Editor()@Html.EditorFor() は、既定のテンプレートを実行するときに htmlAttributes という名前の特殊な ViewDataDictionary エントリを使用します。 この動作は、必要に応じて 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">

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

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

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

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

 

Note

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

Textarea タグ ヘルパー

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

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

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

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

  • 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 の span 要素で asp-validation-for 属性と共に使用されます。

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

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

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

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

Note

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

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

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

検証概要タグ ヘルパー

  • asp-validation-summary 属性を持つ <div> 要素をターゲットとします

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

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

asp-validation-summary 検証メッセージが表示されます
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>
    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">
  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"><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 要素と、関連する option 要素を生成します。

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

Select Tag Helperasp-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>

Note

選択タグ ヘルパーで ViewBag または ViewData を使用することはお勧めしません。 ビュー モデルは、MVC メタデータを提供する場合に堅牢性が高くなり、一般的にあまり問題にはなりません。

asp-for 属性値は特殊なケースであり、(asp-items などの) 他のタグ ヘルパー属性とは異なり、Model プレフィックスは必須ではありません

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

Enum バインディング

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

サンプル:

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 つのグループを次に示します。

option group example

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

選択なし

複数のページで "未指定" オプションを使用しているとわかった場合は、テンプレートを作成して 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>

現在の Country 値に応じて、(selected="selected" 属性を含む) 正しい <option> 要素が選択されます。

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>

その他のリソース