記事内に広告が含まれています

【Blazor】入れ子クラスに対するフォームバリデーション

Blazor入れ子になったクラスに対するバリデーション C#

入れ子になったクラスや、Listなどのコレクション型に対して属性バリデーションを行う方法を解説します。

環境

  • Windows 11
  • Visual Studio 2022
  • .NET 8

問題

Blazorでは属性によるバリデーションが簡単に行えますが、下記のように入れ子になったクラスでは最上位の親クラスに対してのみバリデーションが行われ、子クラスについては無視されてしまいます。
(Listなどのコレクション型も同様にバリデーションが行われない)

using System.ComponentModel.DataAnnotations;

namespace ComponentSample.Components.Pages
{
    /// <summary>
    /// 親クラス
    /// </summary>
    public class Todo
    {
        [Required(ErrorMessage ="Todo名は必須です")]
        public string Name { get; set; } = "";

        public TodoDetails Details { get; set; } = new();
    }

    /// <summary>
    /// 子クラス
    /// </summary>
    public class TodoDetails
    {
        [Required(ErrorMessage = "メモは必須です")]
        public string Memo { get; set; } = "";
    }
}

DataAnnotationsValidatorを用いて、通常通り属性バリデーションを行います。

@page "/todo-form"

<EditForm Model="Model" OnValidSubmit="Submit" FormName="TodoForm">
    <DataAnnotationsValidator />
    <div>
        <label>
            Todo名:
            <InputText @bind-Value="Model!.Name" />
            <ValidationMessage For="() => Model.Name" />
        </label>
    </div>
    <div>
        <label>
            メモ:
            <InputText @bind-Value="Model!.Details.Memo" />
            <ValidationMessage For="() => Model.Details.Memo" />
        </label>
    </div>
    <div>
        <button type="submit">登録</button>
    </div>
    @message
</EditForm>

@code {
    [SupplyParameterFromForm]
    public Todo? Model { get; set; } = new();

    private string? message;

    private void Submit() => message = $"登録しました!  Todo名:{Model?.Name}  メモ:{Model?.Details.Memo}";
}

実行すると、親クラスのプロパティにはバリデーションが行われますが、子クラスのプロパティに対してはバリデーションが行われません。

対策

DataAnnotationsValidatorの代わりにObjectGraphDataAnnotationsValidatorを使用することでこの問題を解決できます。

使用するためにはMicrosoft.AspNetCore.Components.DataAnnotations.Validationというパッケージをインストールする必要があります。

このパッケージは現時点でプレリリース版であるため、本番プロダクトで使用する場合はご注意ください。(.NET 9以降で正式版リリースの計画はあるようです)

インストールしたら、子クラスを参照しているプロパティに[ValidateComplexType]属性を付与します。

    /// <summary>
    /// 親クラス
    /// </summary>
    public class Todo
    {
        [Required(ErrorMessage ="Todo名は必須です")]
        public string Name { get; set; } = "";

        [ValidateComplexType]
        public TodoDetails Details { get; set; } = new();
    }

//以下略

次に、フォームのDataAnnotationsValidatorObjectGraphDataAnnotationsValidatorに置き換えます。

@page "/todo-form"

<EditForm Model="Model" OnValidSubmit="Submit" FormName="TodoForm">
    <ObjectGraphDataAnnotationsValidator />
    <div>
        <label>
            Todo名:
            <InputText @bind-Value="Model!.Name" />
            <ValidationMessage For="() => Model.Name" />
        </label>
    </div>
 
//以下略

実行してみると、子クラスのプロパティにもバリデーションが行われるようになりました。

参考

ASP.NET Core Blazor フォームの検証
Blazor フォームで検証を使用する方法について説明します。
C#Blazor
hiranote

コメント

タイトルとURLをコピーしました