このタスクにはAutoMapperを使用できます。ドメインモデルとビューモデルの間でマッピングするために、すべてのプロジェクトでこれを使用しています。
Application_Start
:でマッピングを定義するだけです。
Mapper.CreateMap<MyItem, MyItemViewModel>();
次に、マッピングを実行します。
public ActionResult Index()
{
MyItem item = ... fetch your domain model from a repository
MyItemViewModel vm = Mapper.Map<MyItem, MyItemViewModel>(item);
return View(vm);
}
また、OnActionExecutedメソッドをオーバーライドし、ビューに渡されたモデルを対応するビューモデルに置き換えるカスタムアクションフィルターを作成できます。
[AutoMap(typeof(MyItem), typeof(MyItemViewModel))]
public ActionResult Index()
{
MyItem item = ... fetch your domain model from a repository
return View(item);
}
これにより、コントローラーのアクションが非常に簡単になります。
AutoMapperには、何かを更新したいときにPOSTアクションで使用できるもう1つの非常に便利なメソッドがあります。
[HttpPost]
public ActionResult Edit(MyItemViewModel vm)
{
// Get the domain model that we want to update
MyItem item = Repository.GetItem(vm.Id);
// Merge the properties of the domain model from the view model =>
// update only those that were present in the view model
Mapper.Map<MyItemViewModel, MyItem>(vm, item);
// At this stage the item instance contains update properties
// for those that were present in the view model and all other
// stay untouched. Now we could persist the changes
Repository.Update(item);
return RedirectToAction("Success");
}
たとえば、Username、Password、IsAdminなどのプロパティを含むUserドメインモデルがあり、ユーザーがユーザー名とパスワードを変更できるが、IsAdminプロパティは絶対に変更できないフォームがあるとします。したがって、ビュー内のhtmlフォームにバインドされたUsernameプロパティとPasswordプロパティを含むビューモデルがあり、この手法を使用すると、IsAdminプロパティは変更されずに、これら2つのプロパティのみが更新されます。
AutoMapperはコレクションでも機能します。単純型間のマッピングを定義したら、次のようにします。
Mapper.CreateMap<MyItem, MyItemViewModel>();
コレクション間でマッピングする場合、特別なことをする必要はありません。
IEnumerable<MyItem> items = ...
IEnumerable<MyItemViewModel> vms = Mapper.Map<IEnumerable<MyItem>, IEnumerable<MyItemViewModel>>(items);
だからもう待つ必要はありません。NuGetコンソールで次のコマンドを入力して、ショーを楽しんでください。
Install-Package AutoMapper