ASP.NET core MVC データバンディングとアノテーション

フォームのページからコントローラー側にデータを渡すときの方法(データバインディング)。

元のフォームは以下。

<form method="post">
    <div class="mb-3">
        <label class="form-label"></label>
        <input type="text" class="form-control" id="firstName">
    </div>
    <div class="mb-3">
        <label class="form-label"></label>
        <input type="text" class="form-control" id="secondName">
    </div>
    <button type="submit" class="btn btn-dark">決定</button>
</form>

バインディングするクラスを作成

上記の場合、FirstNameとSecondNameの持ったクラスModels/ViewModels/CreateNameRequest.csを作成する。

namespace TestApp.Models.ViewModels
{
  public class CreateNameRequest
  {
    public string FirstName {get; set;}
    public string SecondName {get; set;}
  }
}

フォーム側でバインディングの記載を行う

@model TestApp.Model.ViewModels.CreateNameRequest

<form method="post">
    <div class="mb-3">
        <label class="form-label"></label>
        <input type="text" class="form-control" id="firstName" asp-for="FirstName">
    </div>
    <div class="mb-3">
        <label class="form-label"></label>
        <input type="text" class="form-control" id="secondName" asp-for="SecondName>
    </div>
    <button type="submit" class="btn btn-dark">決定</button>
</form>

コントローラー側で受信を記載する

[HttpPost]
public IActionResult Create(CreateNameRequest createNameRequest)
{
  var firstName = createNameRequest.FirstName;
  var secondName = createNameRequest.SecondName;
  return View();
}

ASP.NETでもバインディングするんだな。

バリデーションの追加

ViewModelにアノテーションを追加することでバリデーションを追加できる。

namespace TestApp.Models.ViewModels
{
  public class CreateNameRequest
  {
    [Required(ErrorMessage = "入力必須"]
    public string FirstName {get; set;}
    public string SecondName {get; set;}
  }
}

他にも[Range(min,max)],[RegularExpression()]など、いろいろある。また、独自の検証を作ることもできる。

public class CustomValidate : ValidationAttribute
{
  protected override bool IsValid(object? value)
  {
    if (value is string name)
    {
      return name == "そっくり";
    }
    return false;
  }
}
[Required(ErrorMessage = "入力必須")]  //Ruquiredは先にやらないとエラーメッセージが英語になっちゃう
[TagAddValidation(ErrorMessage = "そっくりじゃない")]
public string Name { get; set; }

そして、コントローラーではModelState.IsValidを確認する。

if (ModelState.IsValid) {
  DoSomething();
  return View("Success");
}
return View();

そして、Viewにはその旨表示するタグを追加

<span class="text-danger field-validation-valid" asp-validation-for="Name"></span>