検証コードを記述せずにユーザー入力を暗黙的に検証する

完了

フォームでは、各値を適切に入力する方法を Web サイト ユーザーに指示する必要がありますが、入力した値も確認する必要があります。 Blazor には、最小限のカスタム コードでこの検証を実行できる簡易ツールが用意されています。

このユニットでは、必要なデータと、ユーザー データを正しく検証して応答するようにフォームを構成する方法を Blazor が把握できるように、モデルに注釈を付ける方法について学習します。

Blazor フォームでユーザー入力を検証する

Web サイト ユーザーから情報を収集する場合は、それが意味を持ち、適切な形式で表示されるのを確認することが重要です。

  • ビジネス上の理由から: ユーザーに適切なサービスを提供するには、電話番号や注文の詳細などの顧客情報が正確である要があります。 たとえば、ユーザーが電話番号を入力したときに、形式に誤りがあることが Web ページですぐにわかれば、後になってコストのかかる遅延が発生するのを防ぐことができます。
  • 技術的な理由: コードで計算や他の処理にフォーム入力を使用している場合、正しく入力しないと、エラーや例外が発生する可能性があります。
  • セキュリティ上の理由:悪意のあるユーザーが、チェックされていない入力フィールドを悪用してコードの注入を試みる可能性があります。

Web サイト ユーザーは、入力した情報が正しい形式で入力されたかをチェックする検証規則を理解しています。 必須フィールドには、多くの場合、アスタリスクまたは必須のラベルが付いています。 値を省略したり、形式が適切ではない値を入力すると、問題を修正する方法を指示する検証メッセージが表示されます。 検証メッセージは、ユーザーがフィールドからタブアウトしたか [送信] ボタンをクリックしたときに表示される可能性があります。

無効なデータをユーザーが送信したフォームの例を次に示します。 この場合、フォームの下部に検証メッセージが表示され、無効なフィールドが赤で強調表示されます。 このフォームは、次の演習で作成します。

Screenshot of an example form displaying feedback for the user about invalid data.

検証メッセージは、できるだけわかりやすいものにしてください。 ユーザーの知識はなにも仮定しないでください。たとえば、すべてのユーザーが有効なメール アドレスの形式を知っているわけではありません。

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] 属性が含まれます。これにより、NamePrice の値が常に入力されます。 また、[Range] 属性を使用して、入力された価格がピザの値段の範囲内であることを確認します。 最後に、[EmailAddress] 属性を使用して、入力された ChefEmail 値が有効な電子メール アドレスであることをチェックします。

モデルで使用できるその他の注釈は次のとおりです。

  • [ValidationNever]:フィールドが検証に含まれないようにする場合は、この注釈を使用します。
  • [CreditCard]:ユーザーから有効なクレジット カード番号を記録する場合は、この注釈を使用します。
  • [Compare]:モデルの 2 つのプロパティが一致する必要がある場合は、この注釈を使用します。
  • [Phone]:ユーザーから有効な電話番号を記録する場合は、この注釈を使用します。
  • [RegularExpression]:正規表現と比較して値の形式を確認するには、この注釈を使用します。
  • [StringLength]:文字列値の長さが最大長を超えないことを確認するには、この注釈を使用します。
  • [Url]:ユーザーから有効な URL を記録する場合は、この注釈を使用します。

Note

正規表現は、文字列をパターンと比較したり、文字列を変更したりするために広く使用されます。 それらを使用して、フォームの値が準拠する必要があるカスタム形式を定義できます。 .NET の正規表現の詳細については、「.NET の正規表現」を参照してください。

検証コンポーネントをフォームに追加する

データ注釈の検証を使用するようにフォームを構成するには、最初に、入力コントロールをモデルのプロパティにバインド済みであることを確認します。 次に、EditForm コンポーネント内の任意の場所に、DataAnnotationsValidator コンポーネント を追加します。 検証で生成されるメッセージを表示するには、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
        }
    }
}

OnValidSubmitOnInvalidSubmit を代わりに使用する場合は、各イベント ハンドラー内で検証状態を確認する必要はありません。

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

自分の知識をチェックする

1.

検証エラーの概要を表示するために EditForm で使用されるコンポーネントは何ですか?

2.

Blazor に付属する標準の入力要素ではないのは、次のうちどれですか?