ヘッダー
C# サンプル集
 

カスタムな入力チェック

2024/4/7

この記事は ASP.NET Core Razor Pages を対象にしています。

 

この記事内のサンプルは、プロジェクトテンプレート「ASP.NET Core Web アプリ」を使用して、PagesフォルダーにこのRazorページを追加する前提です。

 

 

プログラムで入力チェックする

サーバー側のC#で if 文などを使って入力項目のエラー判定をする例を紹介します。

この例では、商品名が入力されている場合のみ数量を必須入力とするチェックを行います。

InlineValidation.cshtml.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace WorkStandard.Pages.validation
{
    public class InlineValidationModel : PageModel
    {
        [BindProperty]
        [DisplayName("商品名")]
        public string? ProductName { get; set; }

        [BindProperty]
        [DisplayName("数量")]
        public int? Count { get; set; }

        public void OnPost()
        {
            //▼カスタムな入力チェック。
            //ModelState.IsValidより前にModelState.AddModelErrorすることで
            //カスタムなエラーを追加できます。

            //この例では商品名が入力されている場合は、数量も入力されているかチェックします。
            if (!string.IsNullOrEmpty(ProductName))
            {
                if (!Count.HasValue || Count <= 0)
                {
                    ModelState.AddModelError(nameof(Count), 
                    "商品名が入力されている場合、数量に1以上を指定してください。");
                }
            }

            if (!ModelState.IsValid)
            {
                return;
            }

            System.Diagnostics.Debug.WriteLine($"エラーなし。{ProductName} {Count}");
        }
    }
}

Debug.WriteLineが表示される場所

 

InlineValidation.cshtml

@page
@model WorkStandard.Pages.validation.InlineValidationModel

<form method="post">
    <div class="mb-3">
        <label asp-for="ProductName"></label>
        <input asp-for="ProductName" class="form-control" />
        <span asp-validation-for="ProductName" class="text-danger"></span>
    </div>
    <div class="mb-3">
        <label asp-for="Count"></label>
        <input asp-for="Count" class="form-control" />
        <span asp-validation-for="Count" class="text-danger"></span>
    </div>
    <div>
        <input type="submit" class="btn btn-primary" />
    </div>
</form>

主なCSSクラスの効果

  • mb-3 下に少し余白(margin)を設けます。→ 余白
  • form-control inputをBootstrapの外観にします。→ フォーム
  • text-danger 文字を赤くして、危険であることを示します。→ テーマカラー
  • btn btn-primary ボタンをBootstrapの外観にして、主要な機能であることを示します。→ ボタン

 

 

カスタムな検証属性を作成する

この例ではカスタム検証属性 SJISByteLength を作成し、ShiftJIS換算でのバイト数をチェックできるようにします。Requiredなど組み込みの検証属性と同様にプロパティに属性として適用することで自動的にチェックを実行できます。

CustomValidation.cshtml.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace WorkStandard.Pages.validation
{
    public class CustomValidationModel : PageModel
    {
        [BindProperty]
        [DisplayName("商品名")]
        [SJISByteLength(10, ErrorMessage = "{0} は Shift JISの範囲で{1}バイト以内で入力してください。")]
        public string? ProductName { get; set; }

        public void OnPost()
        {
            if (!ModelState.IsValid)
            {
                return;
            }

            System.Diagnostics.Debug.WriteLine($"エラーなし。{ProductName}");
        }
    }

    public class SJISByteLengthAttribute: ValidationAttribute
    {
        public int ByteLength { get; init; }

        public SJISByteLengthAttribute(int byteLength) { 
            if (byteLength <=0)
            {
                throw new ArgumentOutOfRangeException($"{nameof(byteLength)}は0以下にできません。");
            }

            this.ByteLength = byteLength;
            this.ErrorMessage = "既定のエラーメッセージ。最終的には FormatErrorMessage がエラーメッセージを生成します。";
        }

        public override bool IsValid(object? value)
        {
            // value が nullの場合、OKとします。この場合のチェックには、Required が使用される想定ですif (value == null)
            {
                return true;
            }

            string strValue = (string)value;

            //System.Text.Encoding.GetEncoding("shift_jis") で SJISエンコーディングを扱えるようにします。
            System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
            var sjis = System.Text.Encoding.GetEncoding("shift_jis");

            //▼SJISでない文字が含まれているか確認する。
            //Unicode文字列をSJISに変換する際、対応していない文字は既定では自動的に?になります。
            //これを利用して変換前後で文字列が変わっていればSJISでない文字が含まれていると仮定します。
            //このチェック方法は簡易的なものであり、すべてのケースで適用できるか検討していません。

            //Unicode文字列をSJISに変換。※.NETの仕様上 string 型の内部形式はすべてUnicode。
            string sjisString = sjis.GetString(sjis.GetBytes(strValue));

            if (strValue != sjisString)
            {
                return false;
            }

            //▼バイト数のチェック
            if (sjis.GetBytes(strValue).Length > ByteLength)
            {
                return false;
            }

            return true;
        }

        public override string FormatErrorMessage(string name)
        {
            return string.Format(System.Globalization.CultureInfo.CurrentCulture, 
                ErrorMessage ?? "", name, ByteLength); 
        }
    }
}

Debug.WriteLineが表示される場所

 

CustomValidation.cshtml

@page
@model WorkStandard.Pages.validation.CustomValidationModel

<form method="post">
    <div class="mb-3">
        <label asp-for="ProductName"></label>
        <input asp-for="ProductName" class="form-control" />
        <span asp-validation-for="ProductName" class="text-danger"></span>
    </div>
    <div>
        <input type="submit" class="btn btn-primary" />
    </div>
</form>

主なCSSクラスの効果

  • mb-3 下に少し余白(margin)を設けます。→ 余白
  • form-control inputをBootstrapの外観にします。→ フォーム
  • text-danger 文字を赤くして、危険であることを示します。→ テーマカラー
  • btn btn-primary ボタンをBootstrapの外観にして、主要な機能であることを示します。→ ボタン

 


English