Why Two Classes, View Model and Domain Model?
I have found that while my domain model gets me 85% of the way to having the fields I want, it has never covered 100% of the values I want on my view. Especially when it comes to permissions and whether or not a user should have access to certain portions of the view.
The design concept I attempt to follow is to have as little logic in my views as possible. This means I have fields in my view model like "CanViewThisField" or "CanEditThisField." When I first started with MVC I would have my domain model be my view model and I was always running into the scenario where I needed just one or two more fields to make my view less cluttered. I've since gone the View Model/Model Builder route and it has worked wonderfully for me. I don't battle my code any longer but am able to enhance my view model as I need to without affecting the domain model.
Another good reason to have a ViewModel is paging large sets of data. You could pass the view an array of Person ( Person[]
) but metadata such as the number of pages, the number of the current page, the size of the page would not belong on the Person
class.
Therefore a PersonListViewModel would solve this issue.
A ViewModel holds only those members which are required by the View. They can usually be thought of as a simplification or a "flattening" of the underlying domain model.
Think of them like this:
- ViewModel: this is the data that is appropriate to render on this view
- Domain model: this is all the information my application needs about this entity in order to perform all it's functionality
For example, my Order class has a member called Customer which is a composition association, that is, my Order has a Customer. This Customer object has members such as Firstname, Lastname, etc... But how would I show this on a "details" view of the order or a list of Orders and the Customers who placed them?
Well, using a ViewModel I can have an OrderListItemViewModel which has a CustomerName member and I can map the combination of Firstname and Lastname from the Customer object to this. This can be done manually, or much preferably using Automapper or similar.
Using this approach, you can have multiple Order ViewModels that are specific to different views, e.g. the Order list view might render the customer name in a different way to the Order details view.
Another advantage of ViewModels is that you can cut down on extraneous data not required of the underlying domain object on a view, e.g. if I'm viewing a list of orders, do I really want to see all the customer's contact information, billing details, etc...? I guess that depends on the purpose of the list but, probably not.
Sometimes you need to display the data in a specific manner (ie, displaying a date in the format mm/dd/yyyy vs. yyyy/mm/dd) and often it is easier to make this property in the view and not in the domain model, where you would (or should) have a mapping to a column in your db.