views:

470

answers:

4

As I understand it, Domain Models are classes that only describe the data (aggregate roots). They are POCOs and do not reference outside libraries (nothing special).

View models on the other hand are classes that contain domain model objects as well as all the interface specific objects like SelectList. A ViewModel includes using System.Web.Mvc;.

A repository pulls data out of a database and feeds them to us through domain model objects. What mechanic or device creates the view model objects, populating them from a database? Would it be a factory that has database access? Would you bleed the view specific classes like System.Web.Mvc in to the Repository? Something else?

For example, if you have a drop down list of cities, you would reference a SelectList object in the root of your View Model object, right next to your DomainModel reference:

public class CustomerForm {
    public CustomerAddress address {get;set;}
    public SelectList cities {get;set;}
}

The cities should come from a database and be in the form of a select list object. The hope is that you don't create a special Repository method to extract out just the distinct cities, then create a redundant second SelectList object only so you have the right data types.

+2  A: 

I would say that populating a view model from a domain object is the responsiblity of the Controller. The controller "Get" action would retrieve the domain object from the repository, create a view model, populate the view model and then pass it to the view.

Mac
+1 - controller "presents" the view with the right data model to bind to (viewmodel)
Rob Fonseca-Ensor
So you create Repository methods to extract drop down list options, then create code in the controller to transform it to a ViewModel? You would probably refactor out the code in the controller as separate methods to keep the responsibility count low, so you would have a bunch of methods hanging out there somewhere in the controller space rather than having some mechanic to house all of them? How do you access the database to populate these ViewModels? Do you really have a ton of Repository methods, one for each DDL, that return these micro-domain objects, and more to convert them?
Dr. Zim
It's appropriate to have this functionality in controller space. If you have a lot of similar drop down lists then there might be some opportunity to refactor it to combine them into a single repository.Then to create the view models you could still group the code together, using a factory or some kind of mappers.Converting the domain objects to view models is certainly one of the challenges for MVC applications. I've found that grouping mapper classes together can help.
Mac
+1  A: 

AutoMapper could be used to convert your models to view-models. Here's a very nice article of how you could use it in your ASP.NET MVC application.

Basically your controller action might look like this:

[AutoMap(typeof(ProductModel), typeof(ProductViewModel))]
public ActionResult Index(int id)
{
    return View(_repository.GetById(id));
}

So you still work with your domain models in the controller and the AutoMap action filter will use AutoMapper to convert the model to a view-model according to a mapping file and pass it to the view.

Darin Dimitrov
When you handle the extra data, like what populates a Drop Down List, do you pull this data from the Repository? Do you create special domain models to handle these "micro" domain models like "City List"? Or is there some other kind of pattern like a Factory that has db access?
Dr. Zim
I found a great writeup on this by Steve Michelotti: http://geekswithblogs.net/michelotti/archive/2009/10/25/asp.net-mvc-view-model-patterns.aspx
Dr. Zim
+2  A: 

I would suggest you to look at CQRS (Command Query Responsibility Segregation). Based on this pattern, you don't really need to get your Model from Repository then map it to ViewModel.

You can dedicate a separate set of classes for retrieving data (querying) and displaying on the View. You can call these classes Providers or whatever you like. These classes can return ViewModel or generic DataSet/DataTable objects. There are 2 benefits in this approach:

1- You don't have to worry about mapping between Model and ViewModel, hence easier coding and maintenance. 2- A lot of times the properties your Model has are not exactly what the user expects to see on the screen. Some developers add new properties to their Model just for the purpose of display, which causes the Model to lose its reality in long term. By returning ViewModel or DataSet/DataTable straight from your Provider without being dependant on your Model, you allow your Model and your ViewModels to evolve separately.

Mosh

Mosh
+1  A: 

you can also use ValueInjecter to generate ViewModels from entities and back

Omu