You could use AutoMapper for this task. I am using it in all projects to map between my domain models and view models.
You simply define a mapping in your Application_Start
:
Mapper.CreateMap<MyItem, MyItemViewModel>();
and then perform the mapping:
public ActionResult Index()
{
MyItem item = ... fetch your domain model from a repository
MyItemViewModel vm = Mapper.Map<MyItem, MyItemViewModel>(item);
return View(vm);
}
and you could write a custom action filter which overrides the OnActionExecuted method and substitues the model that was passed to the view with the corresponding view model:
[AutoMap(typeof(MyItem), typeof(MyItemViewModel))]
public ActionResult Index()
{
MyItem item = ... fetch your domain model from a repository
return View(item);
}
This makes your controller actions pretty simple.
AutoMapper has another very useful method which could be used in your POST actions when you want to update something:
[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");
}
Imagine for example that you had a User domain model containing properties like Username, Password and IsAdmin and that you have a form allowing the user for changing his username and password but absolutely not changing the IsAdmin property. So you would have a view model containing the Username and Password properties bound to an html form in the view and using this technique you will only update those 2 properties, leaving the IsAdmin property untouched.
AutoMapper also works with collections. Once you have defined a mapping between the simple types:
Mapper.CreateMap<MyItem, MyItemViewModel>();
you don't need to do anything special when mapping between collections:
IEnumerable<MyItem> items = ...
IEnumerable<MyItemViewModel> vms = Mapper.Map<IEnumerable<MyItem>, IEnumerable<MyItemViewModel>>(items);
So wait no more, type the following command in your NuGet console and enjoy the show:
Install-Package AutoMapper