ASP.NET Razor Pages を最初から(9)
はじめに
Webアプリケーションで最もよく使われる機能の一つと思われる、Webフォームを作成する機能について見ていく。
その後に、頻繁に使いそうなフォームの作成を支援するタグヘルパーの使い方を簡単に確認する。
簡単なフォームサンプルと流れ
フォーム用に新しくCreate.cshtml、Create.cshtml.csを作成して、CreateModelにフォーム用のプロパティ、NameとEmailを作成する。
public class CreateModel : PageModel
{
[BindProperty]
public string Name { get; set; }
[BindProperty]
public string Email { get; set; }
public void OnGet()
{
}
}
送信するためのフォームを、Create.cshtmlに作成する。
@page
@model ZennSample.Pages.CreateModel
<form method="post">
<div class="form-group">
<label asp-for="Name"></label> <!-- Nameプロパティに名前を合わせる -->
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Email"></label> <!-- Emailプロパティに名前を合わせる -->
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
POSTメソッドで送信するので、CreateModelにPOSTリクエストを受け付けるためのOnPostメソッドを追加する。
public IActionResult OnPost()
{
// 送信されたデータを検証
if (!ModelState.IsValid)
{
// 検証失敗の場合ページを再表示
return Page();
}
// 成功したらリダイレクトする(とりあえずトップページに)
return RedirectToPage("./Index");
}
実行。

NameとEmailを入力するフォームが現れるので、まずは何も入力せずSubmitする。

何も設定していないが画面にrequiredとエラーが表示された。
プロパティに[Required]属性は付けていないが、おそらくプロパティの型がNULLを許容しないstringだからだろう。
次は適当な値を入れてSubmitする。

検証を通過して、トップページにリダイレクトする事が確認できた。

Razorでのフォーム作成は、フォームとそれに対応するプロパティ(モデル)を作成して、OnPostメソッドでIsValidする流れを基本的な流れとして覚えておく。
送信データを検証する
検証用フォーム作成
先ほど作成したCreateModelに、AgeプロパティとCountryプロパティを追加する。
Ageはint、Countryはstringにする。
Countryはセレクトボックスで入力できるようにする。
Create.cshtml.csとCreate.shtmlにコードを追加する。
[BindProperty]
public int Age { get; set; }
[BindProperty]
public string Country { get; set; }
// セレクトボックスの選択肢用のプロパティ
public List<SelectListItem> Countries { get; } = new List<SelectListItem>
{
new SelectListItem { Value = "JP", Text = "Japan" },
new SelectListItem { Value = "MX", Text = "Mexico" },
new SelectListItem { Value = "CA", Text = "Canada" },
new SelectListItem { Value = "US", Text = "USA" },
};
セレクトボックスの各項目はSelectListItemが使われる。
プロパティは、SelectListItemのListを作成しておく。
プロパティの宣言と同時に初期化してしまうのでgetのみ指定しておく。
<div class="form-group">
<label asp-for="Age"></label>
<input asp-for="Age" class="form-control" />
<span asp-validation-for="Age" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Country"></label>
<select asp-for="Country" asp-items="Model.Countries" class="form-control"></select>
<span asp-validation-for="Country" class="text-danger"></span>
</div>
AgeはNameやEmailと同様だが、Countryはセレクトボックスにするので、<select></select>タグを使用する。
asp-for="Country"は同様だが、リスト項目はap-itemsにCountriesプロパティを設定する。
asp-forとの違いとして、asp-forはModel.Nameのように書く必要がないが、asp-itemsはasp-items="Model.Countries"とちゃんとModelと書く必要がある(無いとエラーになる)。

実行すると、セレクトボックスには選択肢が表示され、Ageのところは数字入力になっている。
検証属性を付与する
フォーム部分が完成したので検証属性を各プロパティに付与していく。
よく使いそうなものとしては
| 属性 | 用途 |
|---|---|
| Required | 入力必須 |
| StringLength | 文字列の長さ |
| Range | 数字の範囲 |
| DataType | 日付 |
| RegularExpression | 正規表現 |
| EmailAddress | メールアドレス |
こんなもんだろうか。
各プロパティに適当に付与してみる。
[BindProperty]
[Required]
[StringLength(maximumLength:10,MinimumLength =5, ErrorMessage = "5文字以上10文字以内")]
public string Name { get; set; }
[BindProperty]
[Required]
[EmailAddress]
public string Email { get; set; }
[BindProperty]
[Required]
[Range(18,99, ErrorMessage = "18以上、99以下")]
public int Age { get; set; }
[Required]
[BindProperty]
public string Country { get; set; }

ちゃんと検証ができている事が確認できた。
時間がなかったので雑になってしまった、いつか書き直そうと思う。
しばらくはHack The Boxに取り組む。
Discussion