アイキャッチ画像

ASP.NET – 検証属性で文字列配列の文字数を検証する方法について

ASP.NETでは検証属性のStringLengthAttributeクラスを利用することで文字数が不正なデータを拒否することができるようになります。しかし、文字列配列には利用できません。

当記事では、文字列配列に利用できる検証属性をカスタムバリデーションとして作成していきます。

紹介環境

当記事は以下の環境で作成しています。

  • .Net 8
  • WebAPI

他に利用できる環境

以下の環境でも利用できます。

  • Razor Pages
  • MVC

文字列配列に利用できないのか?

以下のようにStringLengthAttributeクラスを文字列配列に利用します。

[StringLength(5)]
public List<string> Items { get; set; }

結果は以下のようにエラーになります。StringLengthAttributeクラスは文字列で利用するため、配列はキャストエラーになります。

StringLengthAttributeをリストに動作させたときのエラー内容

作成方法について

文字列配列の文字数を検証できるカスタムバリエーションを作成していきます。

ValidationAttributeクラスを継承したカスタムバリエーションが以下のようになります。

using System.ComponentModel.DataAnnotations;
using System.Globalization;

namespace SampleWebApi.ViewModels.Attributes;

public class ListStringLengthAttribute(int maximumLength) : ValidationAttribute
{
    /// <summary>
    /// 最大文字列
    /// </summary>
    public int MaximumLength { get; } = maximumLength;

    /// <summary>
    /// 最低文字列
    /// </summary>
    public int MinimumLength { get; set; }

    private int _index = 0;

    public override bool IsValid(object? value)
    {
        _index = 0;

        if (MaximumLength < 0)
        {
            throw new InvalidOperationException("最大文字数にマイナスが指定されています。");
        }

        if (MaximumLength < MinimumLength)
        {
            throw new InvalidOperationException("最大文字数より最小文字数が大きくなっています。");
        }

        if (value == null) return true;
        // valueを配列文字列に変換
        List<string> strings = (List<string>)value;

        foreach (string s in strings)
        {
            if (s == null) continue;
            if (s.Length < MinimumLength || s.Length > MaximumLength)
            {
                // 検証エラー
                return false;
            }
            _index++;
        }
        // 問題なし
        return true;
    }

    public override string FormatErrorMessage(string name)
    {
        string.IsNullOrEmpty(ErrorMessage);

        string? errorMessage = ErrorMessage;
        if (string.IsNullOrEmpty(errorMessage))
        {
            if (MinimumLength != 0)
            {
                errorMessage = "{0}は{2}文字以下{3}文字以上にする必要があります。({0}[{1}])";
            }
            else
            {
                errorMessage = "{0}は{2}文字以下にする必要があります。({0}[{1}])";
            }
        }

        return string.Format(CultureInfo.CurrentCulture, errorMessage, name, _index, MaximumLength, MinimumLength);
    }
}

IsValidメソッドでは文字列数の検証を行います。返却値をtrueにすることで問題なしになり、falseにすることで検証エラーになります。

FormatErrorMessageメソッドではエラーメッセージを作成しています。

プロパティ

指定できるプロパティは以下の通りです。

プロパティ名内容
MinimumLength最小値を設定できます。
ErrorMessageエラーを設定できます。

エラーメッセージについて

エラーメッセージにはString.Formatを利用しています。そのため、以下のように変換されます。

{0}:プロパティ名

{1}:エラーが発生した配列の位置

{2}:最大文字数

{3}:最小文字数

使用例

using SampleWebApi.ViewModels.Attributes;

namespace SampleWebApi.ViewModels;

public class SampleInfo
{
    /// <summary>
    /// 5文字以下
    /// </summary>
    [ListStringLength(5)]
    public List<string> Items1 { get; set; }

    /// <summary>
    /// 2文字以上 5文字以下
    /// </summary>
    [ListStringLength(5, MinimumLength = 2)]
    public List<string> Items2 { get; set; }

    /// <summary>
    /// エラーメッセージを指定した例
    /// </summary>
    [ListStringLength(5, MinimumLength = 2, ErrorMessage = "{0}[{1}]が {3}文字以上 {2}文字以下 でありません。")]
    public List<string> Items3 { get; set; }
}

おわりに

今回は文字列配列のカスタムバリデーションを紹介してみました。文字数の検証はよく利用しますが、たまに文字列配列の検証もありましたので作成してみました。当記事の内容が役に立てば幸いです。