検証コードを記述せずにユーザー入力を暗黙的に検証する
- 5 分
フォームでは、各値を適切に入力する方法を Web サイト ユーザーに指示する必要がありますが、入力した値も確認する必要があります。 Blazor には、最小限のカスタム コードでこの検証を実行できる簡易ツールが用意されています。
このユニットでは、必要なデータと、ユーザー データを正しく検証して応答するようにフォームを構成する方法を Blazor が把握できるように、モデルに注釈を付ける方法について学習します。
Blazor フォームでユーザー入力を検証する
Web サイト ユーザーから情報を収集する場合は、それが意味を持ち、適切な形式で表示されるのを確認することが重要です。
- ビジネス上の理由: 電話番号や注文の詳細などの顧客情報は、ユーザーに適切なサービスを提供するために正しい必要があります。 たとえば、ユーザーが電話番号を入力したときに、形式に誤りがあることが Web ページですぐにわかれば、後になってコストのかかる遅延が発生するのを防ぐことができます。
- 技術的な理由から:コードで計算やその他の処理にフォーム入力を使用している場合、入力が正しくないと、エラーや例外が発生する可能性があります。
- セキュリティ上の理由から:悪意のあるユーザーは、チェックされていない入力フィールドを悪用してコードを挿入しようとする可能性があります。
Web サイト ユーザーは、入力した情報が正しい形式で入力されたかをチェックする検証規則を理解しています。 必須フィールドは、多くの場合、アスタリスクまたは 必須 ラベルでマークされます。 値を省略したり、形式が適切ではない値を入力すると、問題を修正する方法を指示する検証メッセージが表示されます。 入力規則メッセージは、ユーザーがフィールドの外に移動したとき、または [ 送信 ] ボタンをクリックしたときに表示されることがあります。
無効なデータをユーザーが送信したフォームの例を次に示します。 この場合、フォームの下部に検証メッセージが表示され、無効なフィールドが赤で強調表示されます。 このフォームは、次の演習で作成します。
検証メッセージは、できるだけわかりやすいものにしてください。 ユーザーの知識はなにも仮定しないでください。たとえば、すべてのユーザーが有効なメール アドレスの形式を知っているわけではありません。
Blazor で EditForm
を使用する場合、複雑なコードを記述することなく、汎用性のある検証オプションを用意します。
- モデルでは、各プロパティに対して データ注釈 を使用して、値が必要なタイミングと形式を Blazor に伝えることができます。
EditForm
コンポーネント内に DataAnnotationsValidator コンポーネントを追加します。このコンポーネントは、ユーザーが入力した値に対してモデルの注釈をチェックします。- 送信されたフォームのすべての検証メッセージの概要を表示する場合は、 ValidationSummary コンポーネントを使用します。
- 特定のモデル プロパティの検証メッセージを表示する場合は、 ValidationMessage コンポーネントを使用します。
検証のモデルを準備する
まず、 DataAnnotationsValidator コンポーネントに有効なデータの外観を伝えます。 データ モデルで注釈の属性を使用して、検証制限を宣言します。 次の例について考えます。
using System.ComponentModel.DataAnnotations;
public class Pizza
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
[EmailAddress]
public string ChefEmail { get; set;}
[Required]
[Range(10.00, 25.00)]
public decimal Price { get; set; }
}
このモデルは、Blazing Pizza の担当者がメニューに新しいピザを追加できるフォームで使用します。 これには [Required]
属性が含まれます。これにより、Name
と Price
の値が常に入力されます。 また、[Range]
属性を使用して、入力された価格がピザの値段の範囲内であることを確認します。 最後に、[EmailAddress]
属性を使用して、入力された ChefEmail
値が有効な電子メール アドレスであることをチェックします。
モデルで使用できるその他の注釈は次のとおりです。
[ValidationNever]
:フィールドが検証に含まれないようにする場合は、この注釈を使用します。[CreditCard]
:ユーザーから有効なクレジット カード番号を記録する場合は、この注釈を使用します。[Compare]
:モデルの 2 つのプロパティが一致する必要がある場合は、この注釈を使用します。[Phone]
:ユーザーから有効な電話番号を記録する場合は、この注釈を使用します。[RegularExpression]
:正規表現と比較して値の形式を確認するには、この注釈を使用します。[StringLength]
:文字列値の長さが最大長を超えないことを確認するには、この注釈を使用します。[Url]
:ユーザーから有効な URL を記録する場合は、この注釈を使用します。
注
正規表現は、文字列をパターンと比較したり、文字列を変更したりするために広く使用されます。 それらを使用して、フォームの値が準拠する必要があるカスタム形式を定義できます。 .NET での正規表現の詳細については、「 .NET 正規表現」を参照してください。
検証コンポーネントをフォームに追加する
データ注釈の検証を使用するようにフォームを構成するには、最初に、入力コントロールをモデルのプロパティにバインド済みであることを確認します。 次に、 dataAnnotationsValidator コンポーネントを EditForm
コンポーネント内のどこかに追加します。 検証によって生成されるメッセージを表示するには、 ValidationSummary コンポーネントを使用します。このコンポーネントには、フォーム内のすべてのコントロールのすべての検証メッセージが表示されます。 各コントロールの横に検証メッセージを表示する場合は、複数の ValidationMessage コンポーネントを 使用します。 For
属性を使用して、各 ValidationMessage コントロールをモデルの特定のプロパティに関連付けます。
@page "/admin/createpizza"
<h1>Add a new pizza</h1>
<EditForm Model="@pizza">
<DataAnnotationsValidator />
<ValidationSummary />
<InputText id="name" @bind-Value="pizza.Name" />
<ValidationMessage For="@(() => pizza.Name)" />
<InputText id="description" @bind-Value="pizza.Description" />
<InputText id="chefemail" @bind-Value="pizza.ChefEmail" />
<ValidationMessage For="@(() => pizza.ChefEmail)" />
<InputNumber id="price" @bind-Value="pizza.Price" />
<ValidationMessage For="@(() => pizza.Price)" />
</EditForm>
@code {
private Pizza pizza = new();
}
アプリのフォーム検証を制御する
Blazor では、次の 2 つの時間に検証を実行します。
- フィールド検証 は、ユーザーがフィールドの外に移動したときに実行されます。 フィールド検証により、ユーザーはできるだけ早く検証の問題を認識できます。
- モデルの検証 は、ユーザーがフォームを送信したときに実行されます。 モデル検証により、無効なデータが保存されなくなります。
フォームの検証に失敗すると、 ValidationSummary コンポーネントと ValidationMessage コンポーネントにメッセージが表示されます。 これらのメッセージをカスタマイズするには、モデルの各フィールドのデータ注釈に ErrorMessage
属性を追加します。
public class Pizza
{
public int Id { get; set; }
[Required(ErrorMessage = "You must set a name for your pizza.")]
public string Name { get; set; }
public string Description { get; set; }
[EmailAddress(ErrorMessage = "You must set a valid email address for the chef responsible for the pizza recipe.")]
public string ChefEmail { get; set;}
[Required]
[Range(10.00, 25.00, ErrorMessage = "You must set a price between $10 and $25.")]
public decimal Price { get; set; }
}
組み込みの検証属性は汎用性が高く、正規表現を使用してさまざまな種類のテキスト パターンとの照合を行えます。 しかし、特定または例外的な検証要件がある場合は、組み込みの属性ではそれらの要件を正確に満たすことができない可能性があります。 このような状況では、カスタム検証属性を作成できます。 まず、 ValidationAttribute クラスを継承し、 IsValid メソッドをオーバーライドするクラスを作成します。
public class PizzaBase : ValidationAttribute
{
public string GetErrorMessage() => $"Sorry, that's not a valid pizza base.";
protected override ValidationResult IsValid(
object value, ValidationContext validationContext)
{
if (value != "Tomato" || value != "Pesto")
{
return new ValidationResult(GetErrorMessage());
}
return ValidationResult.Success;
}
}
これで、モデル クラスの組み込み属性を使用する場合に、カスタム検証属性を使用できます。
public class Pizza
{
public int Id { get; set; }
[Required(ErrorMessage = "You must set a name for your pizza.")]
public string Name { get; set; }
public string Description { get; set; }
[EmailAddress(
ErrorMessage = "You must set a valid email address for the chef responsible for the pizza recipe.")]
public string ChefEmail { get; set;}
[Required]
[Range(10.00, 25.00, ErrorMessage = "You must set a price between $10 and $25.")]
public decimal Price { get; set; }
[PizzaBase]
public string Base { get; set; }
}
フォームの送信時にフォーム検証をサーバー側で処理する
EditForm
コンポーネントを 使用する場合、フォームの送信に応答するために次の 3 つのイベントを使用できます。
OnSubmit
: このイベントは、検証の結果に関係なく、ユーザーがフォームを送信するたびに発生します。OnValidSubmit
: このイベントは、ユーザーがフォームを送信し、入力が検証に合格すると発生します。OnInvalidSubmit
: このイベントは、ユーザーがフォームを送信し、入力が検証に不合格になると発生します。
OnSubmit
を使用すると、他の 2 つのイベントは発生しません。 代わりに、EditContext
パラメーターを使用して、入力データを処理するべきかどうかを確認できます。 フォームの送信を処理する独自のロジックを記述する場合は、このイベントを使用します。
@page "/admin/createpizza"
<h1>Add a new pizza</a>
<EditForm Model="@pizza" OnSubmit=@HandleSubmission>
<DataAnnotationsValidator />
<ValidationSummary />
<InputText id="name" @bind-Value="pizza.Name" />
<ValidationMessage For="@(() => pizza.Name)" />
<InputText id="description" @bind-Value="pizza.Description" />
<InputText id="chefemail" @bind-Value="pizza.ChefEmail" />
<ValidationMessage For="@(() => pizza.ChefEMail)" />
<InputNumber id="price" @bind-Value="pizza.Price" />
<ValidationMessage For="@(() => pizza.Price" />
</EditForm>
@code {
private Pizza pizza = new();
void HandleSubmission(EditContext context)
{
bool dataIsValid = context.Validate();
if (dataIsValid)
{
// Store valid data here
}
}
}
OnValidSubmit
と OnInvalidSubmit
を代わりに使用する場合は、各イベント ハンドラー内で検証状態を確認する必要はありません。
@page "/admin/createpizza"
<h1>Add a new pizza</a>
<EditForm Model="@pizza" OnValidSubmit=@ProcessInputData OnInvalidSubmit=@ShowFeedback>
<DataAnnotationsValidator />
<ValidationSummary />
<InputText id="name" @bind-Value="pizza.Name" />
<ValidationMessage For="@(() => pizza.Name)" />
<InputText id="description" @bind-Value="pizza.Description" />
<InputText id="chefemail" @bind-Value="pizza.ChefEmail" />
<ValidationMessage For="@(() => pizza.ChefEMail)" />
<InputNumber id="price" @bind-Value="pizza.Price" />
<ValidationMessage For="@(() => pizza.Price" />
</EditForm>
@code {
private Pizza pizza = new();
void ProcessInputData(EditContext context)
{
// Store valid data here
}
void ShowFeedback(EditContext context)
{
// Take action here to help the user correct the issues
}
}