Why Two Classes, View Model and Domain Model?
Asked Answered
S

5

28

I know it could be bad to use domain models as view models. If my domain model has a property named IsAdmin and I have a Create controller action to create users, someone could alter my form and get it to POST a IsAdmin=true form value, even if I did not expose such a text field in my view. If I'm using model binding then when I committed my domain model, that person would now be an admin. So the solution becomes exposing just the properties I need in the view model and using a tool like AutoMapper to map the property values of my returning view model object to that of my domain model object. But I read that the bind attribute on a class can be used to instruct the Model Binder which properties it should and shouldn't bind. So what really is the reason for making two separate classes (domain model and view model) that essential represent the same thing and then incure overhead in mapping them? Is it more a code organization issue and if so, how am I benefiting?

EDIT

One of the most important reasons I've come across for a View Model that's separate from the Domain Model is the need to implement the MVVM pattern (based on Martin Fowler's PM pattern) for managing complex UIs.

Spermatocyte answered 1/2, 2011 at 17:23 Comment(1)
Check out this question too #3095133Provenance
P
22

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.

Provenance answered 1/2, 2011 at 17:28 Comment(6)
I agree with making the view less cluttered but couldn't we abstract this type of functionality to the domain model instead of the view model? I said this earlier but couldn't I use a DisplayAddress() function on my domain model which would combine the domain properties like Address, City, State and Zip? The db only maps properties not functions.Spermatocyte
Obviously anything is possible, just depends on which way you want to go. I have my domain model generated for me, so I don't really touch that code. If you're using any kind of ORM, then that is the case. The view model has allowed for the most flexibility for me without compromising performance either.Provenance
Sorry but I did not follow the link you gave until now. I've concluded that deciding whether or not to take the domain-model-view-model route depends on the demands of the domain model. I can see how some of my domain model objects would make use of a view model while some won't (although that might confuse someone - I'll think more about it). Either way, I've got my answer. Thank you everyone!Spermatocyte
I'm not using an ORM now but I will soon. I know I can use a EntityFramework class in a typed view but I'm not sure how I would decorate auto-generated classes with attributes if they will constantly be deleted?!? Thanks for the heads up.Spermatocyte
@Spermatocyte If you need to decorate auto-generated classes, you can use either partial classes or 'buddy classes'.Musette
Thanks! So I guess, with the EF ORM, the buddy class would be my view model and the auto-gen entity class would be my domain model - sounds like I'm forced to give every auto-gen entity class a view model if only to use the cool validation attributes. But I read that AutoMapper is very slow when dealing with large amounts of data due to it's complex mapping logic. If you know a more efficient solution out there, please link me to itSpermatocyte
E
16

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.

Estipulate answered 18/5, 2011 at 12:16 Comment(0)
A
4

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.

Alboin answered 10/10, 2013 at 12:51 Comment(0)
M
2

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.

Mahdi answered 1/2, 2011 at 17:39 Comment(2)
Thank you, that makes sense. But still, couldn't we just make functions on the domain model to do this? Like DisplayAddress() which would combine the domain properties like Address, City, State and Zip? The db only maps properties not functions. Is this idea a violation of some design philosophy?Spermatocyte
In a way, yes. You could do all of this in the domain model if you really wanted to and it would work just the same. However, I've never seen that work very well from a maintenance. Typically, I've seen these kinds of things put into the view model (or whatever presentation model you're using). So really, it is just an organizational issue than anything. :)Mahdi
O
2

you need to remember that your domain model classes are only used internally; that is, they are never sent to the client. That’s what your service model types (View Model types) are used for—they represent the data that will be going back and forth between the client and your service.

Oilstone answered 9/1, 2014 at 14:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.