📘

.NET 8 Preview 2で追加された入力値検証について

2023/03/18に公開

https://devblogs.microsoft.com/dotnet/announcing-dotnet-8-preview-2/#system-componentmodel-dataannotations-extensions

.NET 8 Preview 2で新たにいくつかの入力値検証が追加されている。これらについて動作を見ていきたい。
Blazor WebAssemblyのプロジェクトで以下のようにフォームとモデルを作成した。

@using DataAnnotationsTest8pre2.Models;

<PageTitle>Index</PageTitle>
@Message
<EditForm Model="@model" OnValidSubmit="@ValidSubmit" OnInvalidSubmit="@InvalidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <p><label>変更しないとダメ</label>
    <InputDate @bind-Value="model.Col1" />
    </p>
    <p><label>0~10(境界値を含む)</label>
    <InputNumber @bind-Value="model.Col2" />
    </p>
    <p><label>0から10(境界値はダメ)</label>
    <InputNumber @bind-Value="model.Col3" />
    </p>
    <p><label>8文字から20文字</label>
    <InputText @bind-Value="model.Col4" />
    </p>
    <p>
        <label>Microsoft,Apple,Amazon,Facebook,GoogleのみOK</label>
    <InputText @bind-Value="model.Col5" />
    </p>
    <p>
        <label>Excel,Wordはダメ</label>
    <InputText @bind-Value="model.Col6" />
    </p>
    <button type="submit">送信</button>
</EditForm>

@code {
    private TestModel model = new();

    private string? Message;

    private void ValidSubmit()
    {
        Message = "モデル検証OK";
    }

    private void InvalidSubmit()
    {
        Message = "モデル検証NG";
    }
}
    public class TestModel
    {
        [Required(DisallowAllDefaultValues = true)]
        public DateOnly Col1 { get; set; } //= DateOnly.FromDateTime(DateTime.Now);
        [Range(0, 10, MinimumIsExclusive = false, MaximumIsExclusive = false)]
        public int Col2 { get; set; }
        [Range(0, 10, MinimumIsExclusive = true, MaximumIsExclusive = true)]
        public int Col3 { get; set; }
        [Length(8,20)]
        public string Col4 { get; set; } = "password";
        [AllowedValues("Microsoft","Apple","Amazon","Facebook","Google")]
        public string Col5 { get; set; } = "Microsoft";
        [DeniedValues("Excel", "Word")]
        public string Col6 { get; set; } = "PowerPoint";
    }

まず、追加された属性の一つ目。
[Required(DisallowAllDefaultValues = true)]
これは、構造体がデフォルト値から変更されていないとモデル検証に失敗する。
すなわち、DateOnlyの場合は「0001/01/01」より変更されている必要がある。ここでいうデフォルト値は自動プロパティの初期化された値ではなくその構造体のデフォルト値のことである。

二つ目。
[Range(0, 10, MinimumIsExclusive = true, MaximumIsExclusive = true)]
Range属性にMinimunIsExclusiveとMaximumIsExclusiveが追加されている。
これは、それぞれ下限と上限の境界値をOKとするかNGとするかという意味である。これをtrueとすることで境界値がNGとなるので上記の場合のCol3プロパティは0や10はモデル検証に失敗する。

三つ目
[Length(8,20)]
Length属性で文字列またはコレクションの長さの範囲を指定できるようになった。
特に文字列長の指定をすることが多いと思われるが従来は最大文字列長を指定する組み込みのデータ検証はあったが下限は指定することができなかった。
これはとても便利に感じる。

四つ目
[AllowedValues("Microsoft","Apple","Amazon","Facebook","Google")]
AllowedValuesでプロパティの許可リストを指定できるようになった。
上記の場合、Microsoft,Apple,Amazon,Facebook,Googleのみの文字列のみモデル検証に成功する。

五つ目
[DeniedValues("Excel", "Word")]
DeniedValuesでプロパティの拒否リストを指定できるようになった。
上記の場合、Excel,Wordという文字列でモデル検証に失敗する。

https://github.com/tomokusaba/DataAnnotationsTestDotnet8pre2

Discussion