miso_soup3 Blog

主に ASP.NET 関連について書いています。

AutoMapper + ViewModel In MVC その1

MVCで書くときのポイント、

この2点のうち、その1を書きたいと思います。

その1.適切なViewModelを作る

MVCでゴリゴリ書いていると、適切なViewModelを作ることが
大事だなと感じます。
このあたりの設計パターンの説明はできませんが、
ViewModelを作らないと、どんな困ったことがおきるか?
具体例を発見したので記載します。

例えばイベント管理アプリ。
イベントは、タイトルと、予定日(Null許可)の2つの項目をもっています。

このModelとViewModelを使って、以下の用に「イベント一覧」を作成したとします。

「イベント一覧」の View
<h2>イベント一覧</h2>
<table>
	<tr>
		<td>タイトル</td>
		<td>予定日</td>
	</tr>
	<tr>
		@foreach (var projectEvent in Model.ProjectEvents)
		{	  
			<td>@projectEvent.Title</td>
			<td>
				@if(projectEvent.PlanDate.HasValue)
				{
					@projectEvent.PlanDate.Value
				}
			</td>
		}
	</tr>
</table>

で、次。
「イベント一覧」の他に、「今週のイベント一覧」を作成するときはどうするか、です。

先程のViewModelであるProjectEventViewを使いまわすと、
以下のようになってしまいます。

「今週のイベント一覧」の View
<h2>今週のイベント一覧</h2>
<table>
	<tr>
		<td>日付</td>
		<td>タイトル</td>
	</tr>
	<tr>
		@foreach (var projectEvent in Model.ProjectEvents)
		{		
			<td>
				@if (projectEvent.PlanDate.HasValue)
				{
					@projectEvent.PlanDate.Value
				}
			</td>
			<td>@projectEvent.Title</td>
		}
	</tr>
</table>

「イベント一覧」のコードとあまり差がないんですが・・・。
「今週のイベント一覧」なのに、なんで予定日がNullかもしれないの?if文いらなくない?
と開発者が疑問に思います。
余計なコードは書きたくないですし、バグも発生しやすくなります。

解決策は、「今週のイベント一覧」にあうViewModelを別に作ることです。

PlanDateが、DateTime?ではなく、DateTime型になっています。
もっと突き詰めると、

とかも良いと思います。

おしまい

以上のように、ページの概念に基づいた適切なViewModelを作成することで、
自然なコードがかけるようになります。
Model 1コに対し、ViewModelはいくつでも作ってよいと思います。

ModelからViewModelを作成する際には、AutoMapperを使っています。
次はその辺りを書きます。(書きました。→その2.AutoMapperのテスト、確認

おまけ FormModel

Controller側では、ViewModelを作成・組み立てたりしない方が良いです。
また、ViewModelとは別に、FormModelを
画面:FormModel = 1 : 1 で作成するといろいろ便利でした。
(Razor側で変更があった時に、余計な修正を加えなくて済みません。)
(FormModelとは私がそう呼んでいるだけで、ModelとかContainerと呼称するサンプルもありました。)

public ActionResult List()
{
	var response = _service.GetAllProjectEvent();
	IEnumerable<ProjectEventView> events = response.ProjectEvents;

	var model = new ProjectEventListFormModel();
	model.ProjectEvents = events;
	return View(model);
}