Razor Pagesのフォームの入力内容を独自の処理で検証する - ASP.NET Core

Razor Pagesのフォームの入力内容を独自の処理で検証するコードを紹介します。

概要

こちらの記事ではRazor Pagesのシンプルな入力内容の検証を実装しました。 この記事では、入力された内容を独自のロジックで検証するプログラムのコードを紹介します。

実装方針

入力内容が送信される際に、IsValid メソッドが呼び出されます。
IsValidメソッドをオーバーライドし独自の検証ロジックを実装します。検証に成功した場合は、ValidationResult.Success を返し、失敗した場合は、 エラーメッセージを含めた ValidationResult 負ぶえジェクトを返します。
補足
フォームの入力値をクラスのメンバプロパティに代入する場合に、 クラスに対して検証処理を実行する方法はこちらの記事を参照してください。

プログラム例1

ASP.NET Core アプリケーションを作成し、以下のファイル、コードを記述します。

コード

Pages/CustomValidation01.cshtml
@page
@model RazorPagesValidation.Pages.CustomValidation01Model
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

@{
}
<html>
  <head></head>
  <body>
    <h2>入力内容のカスタム検証のデモ</h2>
    <form method="post">
      <input type="text" asp-for="inputText"/>
      <input type="submit" value="Exec" />
    </form>

    <p>@Model.MessageText</p>
  </body>
</html>
Pages/CustomValidation01.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc.ModelBinding;

namespace RazorPagesValidation.Pages
{
  public class MyValueAttribute : ValidationAttribute
  {
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
      string svalue = (string)value;

      if (svalue == "Penguin" || svalue == "Duck")
      {
        return ValidationResult.Success;
      }
      else
      {
        return new ValidationResult("Invalid Value");
      }

    }
  }

  public class CustomValidation01Model : PageModel
  {

    [BindProperty]
    [MyValueAttribute]
    public string inputText { get; set; }

    public string MessageText { get; set; }

    public void OnGet()
    {
    }

    public PageResult OnPost()
    {
      if (ModelState.IsValid == true)
      {
        MessageText = "処理は成功しました。";
        return Page();
      }
      else
      {
        foreach (ModelStateEntry se in ModelState.Values)
        {
          foreach (ModelError me in se.Errors)
          {
            MessageText += me.ErrorMessage;
          }
        }
        return Page();
      }
    }

  }
}
Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.Build();

app.UseStaticFiles();
app.UseRouting();
app.MapRazorPages();
app.Run();

解説

カスタムの検証ロジックを実装する場合、検証処理を実装する ValidationAttribute クラスを継承したカスタムの継承クラスを作成します。 今回は MyValueAttribute クラスとしています。
IsValidメソッドをオーバーライドし、検証する処理をメソッド内に実装します。 検証が正しかった場合は、ValidationResult.Success を返し、 誤っていた場合は、ValidationResult オブジェクトを返します。ValidationResult オブジェクトのコンストラクタの第一引数に、エラーとなるメッセージを与えます。
フィールド(テキストボックス等)に入力された値は、IsValidの第一引数のvalue変数に設定されます。
今回の例では、テキストボックスの入力文字列が、"Penguin" "Duck" の場合は問題なしとし、 それ以外の値が入力された場合は、無効な値としてエラーを返す実装としています。
public class MyValueAttribute : ValidationAttribute
{
  protected override ValidationResult IsValid(object value, ValidationContext validationContext)
  {
    string svalue = (string)value;

    if (svalue == "Penguin" || svalue == "Duck")
    {
      return ValidationResult.Success;
    }
    else
    {
      return new ValidationResult("Invalid Value");
    }
  }
}

検証ロジックを適用する入力プロパティには [(ValidationAttributeを継承したカスタム検証クラス)] の属性を記述します。 今回の例では、ValidationAttributeクラスを継承した、MyValueAttribute クラスを属性に記述します。
    [BindProperty]
    [MyValueAttribute]
    public string inputText { get; set; }

検証ロジックを実行する部分です。通常は、OnPostメソッドでフォームの内容が送信された際にModelState.IsValid プロパティの値を確認します。 trueであれば検証は成功し、処理を続行します。falseの場合は検証に失敗したことになるため、エラーメッセージを表示します。 エラーメッセージは、ModelState.Valuesプロパティの Errors プロパティにメッセージが設定されています。複数のエラーメッセージが 設定されている場合もあるため、Errors プロパティの値をループ等で取得しページに出力します。
public PageResult OnPost()
{
  if (ModelState.IsValid == true)
  {
    MessageText = "処理は成功しました。";
    return Page();
  }
  else
  {
    foreach (ModelStateEntry se in ModelState.Values)
    {
      foreach (ModelError me in se.Errors)
      {
        MessageText += me.ErrorMessage;
      }
    }
    return Page();
  }
}

実行結果

プロジェクトを実行し、(アプリケーションルートURL)/CustomValidation01 にアクセスします。下図のウィンドウが表示されます。


テキストボックスに Bear を入力します。


[Exec]ボタンをクリックします。入力値が"Penguin" "Duck"以外なので、検証に失敗し "Invalid Value" のメッセージが表示されます。


続いて、テキストボックスに "Penguin" を入力します。入力後[Exec]ボタンをクリックします。


クリックすると、検証が成功し "処理は成功しました。" のメッセージが表示されます。


テキストボックスに "Duck" を入力した場合も同様に成功します。

プログラム例2:入力要素が複数ある場合

ASP.NET Coreアプリケーションを作成します。

コード

以下のコードを記述します。
Pages/CustomValidation02.cshtml
@page
@model RazorPagesValidation.Pages.CustomValidation02Model
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
  <head></head>
  <body>
    <h2>入力内容のカスタム検証のデモ</h2>
    <form method="post">
      <input type="text" asp-for="inputText1"/><br />
      <text>@Model.ErrorMessageText1</text><br/>
      <input type="text" asp-for="inputText2"/><br />
      <text>@Model.ErrorMessageText2</text><br/>
      <input type="text" asp-for="inputText3"/><br />
      <text>@Model.ErrorMessageText3</text><br/>
      <input type="submit" value="Exec" />
    </form>
        <p>@Model.MessageText</p>
  </body>
</html>
Pages/CustomValidation02.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc.ModelBinding;

namespace RazorPagesValidation.Pages
{
  public class MyValue1Attribute : ValidationAttribute
  {
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
      string svalue = (string)value;

      if (svalue == "Penguin" || svalue == "Duck") {
        return ValidationResult.Success;
      }
      else {
        return new ValidationResult("Penguin か Duck のどちらかを入力してください。");
      }

    }
  }

  public class MyValue2Attribute : ValidationAttribute
  {
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
      int ivalue;
      if (int.TryParse((string)value, out ivalue) == true) {
        return ValidationResult.Success;
      }
      else {
        return new ValidationResult("数値を入力してください。");
      }
    }
  }

  public class MyValue3Attribute : ValidationAttribute
  {
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
      string svalue = (string)value;

      System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex("^[A-Z]$");
      System.Text.RegularExpressions.Match match = reg.Match(svalue);

      if (match.Success == true) {
        return ValidationResult.Success;
      }
      else {
        return new ValidationResult("AからZの大文字一文字を入力してください。");
      }
    }
   
  }


  public class CustomValidation02Model : PageModel
  {
    [BindProperty]
    [MyValue1Attribute]
    public string inputText1 { get; set; }

    [BindProperty]
    [MyValue2Attribute]
    public string inputText2 { get; set; }

    [BindProperty]
    [MyValue3Attribute]
    public string inputText3 { get; set; }

    public string ErrorMessageText1 { get; set; }
    public string ErrorMessageText2 { get; set; }
    public string ErrorMessageText3 { get; set; }
    public string MessageText { get; set; }

    public void OnGet()
    {
    }

    public PageResult OnPost()
    {
      if (ModelState.IsValid == true) {
        MessageText = "処理は成功しました。";
      }
      else {
        ErrorMessageText1 = "";
        if (ViewData.ModelState["inputText1"] != null) {
          ModelStateEntry mse = ViewData.ModelState["inputText1"]!;
          foreach (ModelError me in mse.Errors) {
            ErrorMessageText1 += me.ErrorMessage;
          }
        }

        if (ViewData.ModelState["inputText2"] != null) {
          ModelStateEntry mse = ViewData.ModelState["inputText2"]!;
          ErrorMessageText2 = "";
          foreach (ModelError me in mse.Errors) {
            ErrorMessageText2 += me.ErrorMessage;
          }
        }

        if (ViewData.ModelState["inputText3"] != null) {
          ModelStateEntry mse = ViewData.ModelState["inputText3"]!;
          ErrorMessageText3 = "";
          foreach (ModelError me in mse.Errors) {
            ErrorMessageText3 += me.ErrorMessage;
          }
        }

      }

      return Page();
    }

  }
}

解説

複数の入力プロパティがあり、それぞれの検証ロジックが違う場合、別々のValidationAttributeから派生した検証クラスを割り当てます。
    [BindProperty]
    [MyValue1Attribute]
    public string inputText1 { get; set; }

    [BindProperty]
    [MyValue2Attribute]
    public string inputText2 { get; set; }

    [BindProperty]
    [MyValue3Attribute]
    public string inputText3 { get; set; }

検証ロジックのクラスです。MyValue1Attribute は入力文字列が "Penguin" か "Duck" のどちらかの入力でないとエラーとします。 MyValue2Attribute は入力値が数値でないとエラーとします。MyValue3Attribute はAからZの大文字1文字でないとエラーとします。
  public class MyValue1Attribute : ValidationAttribute
  {
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
      string svalue = (string)value;

      if (svalue == "Penguin" || svalue == "Duck") {
        return ValidationResult.Success;
      }
      else {
        return new ValidationResult("Penguin か Duck のどちらかを入力してください。");
      }

    }
  }

  public class MyValue2Attribute : ValidationAttribute
  {
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
      int ivalue;
      if (int.TryParse((string)value, out ivalue) == true) {
        return ValidationResult.Success;
      }
      else {
        return new ValidationResult("数値を入力してください。");
      }
    }
  }

  public class MyValue3Attribute : ValidationAttribute
  {
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
      string svalue = (string)value;

      System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex("^[A-Z]$");
      System.Text.RegularExpressions.Match match = reg.Match(svalue);

      if (match.Success == true) {
        return ValidationResult.Success;
      }
      else {
        return new ValidationResult("AからZの大文字一文字を入力してください。");
      }
    }

実行結果

プロジェクトを実行します。(アプリケーションルートURL)/CustomValidation02 のURLにアクセスします。 下図のページが表示されます。


上のテキストボックスから順に "a" "b" "c" を入力します。


[Exec]ボタンをクリックします。すべて不適の入力になるため、バリデーションエラーのメッセージがテキストボックスの下部に表示されます。


続いて、テキストボックスで上から順に "Penguin" "200" "G" を入力し、[Exec]ボタンをクリックします。


すべての検証が通り、"処理は成功しました。"のメッセージが表示されます。


テキストボックスに "Penguin" "AAB" "G" を入力し、[Exec]ボタンをクリックします。
2番目のテキストボックスの検証に失敗し、2番目のテキストボックスの下部にのみバリデーションエラーのメッセージが表示されます。


テキストボックスに "Camel" "AAB" "G" を入力し、[Exec]ボタンをクリックします。
1番目と2番目のテキストボックスの検証に失敗し、2つのテキストボックスの下部にバリデーションエラーのメッセージが表示されます。


Razor Pagesで入力フォームの検証処理が実装できました。

著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2023-03-22
作成日: 2022-07-28
iPentec all rights reserverd.