ASP.NET MVC で言う Model がどういうものかについて書いておきます。ネットの記事などで目にする一般的な MVC の Model の説明とは少々違っていて理解し難いかもしれませんので (実は自分がそうでした)。
上の画像はマイクロソフト公式解説書「プログラミング Microsoft ASP.NET MVC」に記載されている図を借用したものです。ASP.NET MVC には「入力モデル」「ビューモデル」「ドメインモデル」という 3 種類の Model があることを示しています。それら各モデルが重なっている点にも注意してください。
重なっているのは、Model 自体は一つのクラスとして定義されており同じものですが、使われ方によって「入力モデル」「ビューモデル」「ドメインモデル」というように役割が変わるということと理解すれば良いと思います。
一方、ネットなどでよく目にする一般的な MVC の Model の説明は、例えば Wikipedia の記事 Model View Controller にあるように「アプリケーションデータ、ビジネスルール、ロジック、関数」という役割を持ち、クライアント側から見て View と Controller の背後にあるという構成で説明されていることが多いと思います。
ASP.NET MVC の 3 種類の Model のうち、「ドメインモデル」が上で言う「アプリケーションデータ、ビジネスルール、ロジック、関数」に近いものです。
「ビューモデル」は Controller から View にデータを渡すために使われます。「入力モデル」はクライアントから送信されてくるデータを Controller のアクションメソッドに渡す時に使われます。
以下に説明のための具体例を書きます。
まず、プロジェクトの Models フォルダに、以下の Student クラスの定義(即ち、Model の定義)を含むクラスファイルがあるとします。
using System;
using System.Collections.Generic;
namespace Mvc5App.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
}
}
さらに、データーベースに Student テーブルがあって、それを Entity Framework を利用して編集・更新を行うための Controller と View を作るとします。
編集用の画面を表示するための Controller のアクションメソッドは以下のようになります。
public async Task<ActionResult> Edit(int? id)
{
Student student = await db.Students.FindAsync(id);
return View(student);
}
db.Students.FindAsync(id) の db は DbContext クラスを継承するコンテキストクラスで、Entity Framework を利用してデータベースへのクエリの実行などを行うものです。このコードでは、指定された id のレコードをデータベースから取得して Student オブジェクトを作っています。その部分は上の図で「ドメインモデル」に該当します。
return View(student) で View に Student オブジェクトを渡していますが、それが「ビューモデル」に該当します。
アクションメソッドに対応する View (Edit.cshtml) のコードの一行目に @model Mvc5App.Models.Student と書けば、View の中では Model プロパティで Student オブジェクトを取得できます。また、EditorFor などの Html ヘルパーでは、例えばその引数を model => model.LastName とすれば model に Student オブジェクトが渡されます。
View によって html ソースが生成されクライアント (ブラウザ) に送信されます。ユーザーがブラウザに表示されたテキストボックスの内容を編集後、ボタンクリック操作などでデータを送信するとサーバー側ではモデルバインディングという操作が行われます。
ブラウザから送信されてきたデータを受け取ってデーターベースを更新する Controller のアクションメソッドは以下のようになっています。モデルバインディングというのは、送信されてきたデータで Student オブジェクトを作成し、それをアクションメソッドの引数 student に渡す操作ですが、その時使うのが上の図の「入力モデル」になります。
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(Student student)
{
if (ModelState.IsValid)
{
db.Entry(student).State = EntityState.Modified;
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(student);
}
ModelState.IsValid が true の場合(送信データの検証結果が OK の場合)、if 文の中の最初の 2 行で既存のレコードが更新されます。その部分も上の図で「ドメインモデル」に該当します。
ASP,NET MVC アプリを作っているときに目立つのが「ビューモデル」と「入力モデル」と思いますが、それらは上に紹介した Wikipedia の記事にあるような一般的な MVC の Model の説明の機能「アプリケーションデータ、ビジネスルール、ロジック、関数」は持たないので、説明と違うということが混乱を招くところと思います。