1. ホーム
  2. asp.net-mvc

[解決済み] MVCにおけるViewModelとは?

2022-03-22 15:23:46

質問

ASP.NET MVCの初心者です。ViewModelの目的を理解するのに問題があります。

ViewModel とは何ですか?また、なぜ ASP.NET MVC アプリケーションに ViewModel が必要なのでしょうか?

その動作と説明について良い例があれば、より良いのですが。

解決方法は?

A view model は、ビュー/ページに表示するデータを表します。静的なテキストとして使用するか、データベースに追加 (または編集) できる入力値 (テキストボックスやドロップダウンリストなど) として使用するかは問いません。これは domain model . これは、ビューのモデルです。

があるとします。 Employee クラスは従業員ドメインモデルを表し、次のプロパティ (一意な識別子、姓、名、および作成日) を含んでいます。

public class Employee : IEntity
{
     public int Id { get; set; }

     public string FirstName { get; set; }

     public string LastName { get; set; }

     public DateTime DateCreated { get; set; }
}

ビューモデルはドメインモデルとは異なり、ビュー上で使用したいデータ(プロパティで表される)だけを含むモデルです。 例えば、新しい従業員レコードを追加したいとすると、ビューモデルは次のようになります。

public class CreateEmployeeViewModel
{
     public string FirstName { get; set; }

     public string LastName { get; set; }
}

見てわかるように、これには2つのプロパティしか含まれていません。この2つのプロパティは、従業員ドメイン・モデルにも含まれています。 これはなぜか、と聞かれるかもしれません。 Id はビューから設定されるのではなく、Employeeテーブルによって自動生成される可能性があります。 また DateCreated は、ストアドプロシージャやアプリケーションのサービスレイヤーで設定されるかもしれません。 そのため IdDateCreated はビューモデルでは必要ありません。従業員の詳細(すでに捕捉されている従業員)を表示する際に、この2つのプロパティを静的テキストとして表示したい場合があります。

ビュー/ページを読み込む際に、従業員コントローラの create アクションメソッドはこのビューモデルのインスタンスを作成し、 必要に応じてフィールドに情報を入力し、 このビューモデルをビュー/ページに渡します。

public class EmployeeController : Controller
{
     private readonly IEmployeeService employeeService;

     public EmployeeController(IEmployeeService employeeService)
     {
          this.employeeService = employeeService;
     }

     public ActionResult Create()
     {
          CreateEmployeeViewModel model = new CreateEmployeeViewModel();

          return View(model);
     }

     public ActionResult Create(CreateEmployeeViewModel model)
     {
          // Do what ever needs to be done before adding the employee to the database
     }
}

ビュー/ページは次のようになります。 ASP.NET MVC であり Razor ビューエンジン)。

@model MyProject.Web.ViewModels.CreateEmployeeViewModel

<table>
     <tr>
          <td><b>First Name:</b></td>
          <td>@Html.TextBoxFor(m => m.FirstName, new { maxlength = "50", size = "50" })
              @Html.ValidationMessageFor(m => m.FirstName)
          </td>
     </tr>
     <tr>
          <td><b>Last Name:</b></td>
          <td>@Html.TextBoxFor(m => m.LastName, new { maxlength = "50", size = "50" })
              @Html.ValidationMessageFor(m => m.LastName)
          </td>
     </tr>
</table>

このように、バリデーションは FirstNameLastName . 使用方法 FluentValidation(フルエントバリデーション のようなバリデーションを行うことができます。

public class CreateEmployeeViewModelValidator : AbstractValidator<CreateEmployeeViewModel>
{
     public CreateEmployeeViewModelValidator()
     {
          RuleFor(m => m.FirstName)
               .NotEmpty()
               .WithMessage("First name required")
               .Length(1, 50)
               .WithMessage("First name must not be greater than 50 characters");

          RuleFor(m => m.LastName)
               .NotEmpty()
               .WithMessage("Last name required")
               .Length(1, 50)
               .WithMessage("Last name must not be greater than 50 characters");
     }
}

そして、Data Annotationsを使用すると、次のようになります。

public class CreateEmployeeViewModel : ViewModelBase
{
    [Display(Name = "First Name")]
    [Required(ErrorMessage = "First name required")]
    public string FirstName { get; set; }

    [Display(Name = "Last Name")]
    [Required(ErrorMessage = "Last name required")]
    public string LastName { get; set; }
}

覚えておくべき重要なことは、ビューモデルは、あなたが使いたいデータのみを表すということです それ以外には何もありません。 もし、30個のプロパティを持つドメインモデルがあって、1つの値だけを更新したい場合、すべての不要なコードと検証を想像することができます。 このシナリオでは、ドメインオブジェクトにあるすべてのプロパティではなく、ビューモデルにあるこの1つの値/プロパティのみを持つことになります。

ビューモデルは、1つのデータベース・テーブルからのデータだけを持つとは限りません。別のテーブルのデータを組み合わせることもできます。新しい従業員レコードを追加することについて、上記の私の例を見てください。姓と名を追加するだけでなく、その従業員の部署を追加したいかもしれません。この部門のリストは、あなたの Departments テーブルを使用します。これで EmployeesDepartments テーブルを1つのビューモデルに統合します。あとは、以下の2つのプロパティをビューモデルに追加して、データを投入するだけです。

public int DepartmentId { get; set; }

public IEnumerable<Department> Departments { get; set; }

従業員データ(すでにデータベースに追加されている従業員)を編集する場合は、上記の例とあまり変わりません。 ビューモデルを作成し、それを例えば EditEmployeeViewModel . このビューモデルには、姓や名のような編集したいデータだけを入れておきます。データを編集して、送信ボタンをクリックします。私なら、あまり気にせず Id フィールドは Id の値は、おそらく URL などに含まれていることでしょう。

http://www.yourwebsite.com/Employee/Edit/3

これを持って Id を作成し、姓と名の値とともにリポジトリレイヤーに渡します。

レコードを削除する場合、私は通常、編集ビューモデルと同じ経路をたどります。また、例えばURLも用意します。

http://www.yourwebsite.com/Employee/Delete/3

ビューが初めてロードされたとき、私は、データベースから Id その後、削除される従業員がわかるように、ビュー/ページに静的テキストを表示します。ユーザーが削除ボタンをクリックすると、私は単に Id の値を3にして、リポジトリレイヤーに渡します。必要なのは Id を使用してテーブルからレコードを削除します。

もう一点、すべてのアクションにビューモデルが必要なわけではありません。単純なデータなら EmployeeViewModel . もし、複雑なビューやページがあり、それらが互いに異なる場合は、それぞれに別のビューモデルを使用することをお勧めします。

これで、ビューモデルとドメインモデルについて持っていた混乱が解消されれば幸いです。