11

I'm building a concept application with MVC 3 in an attempt to learn its ways. I've previously done some very heavy-duty applications in WebForms, using an n-tier approach, usually consisting of domain objects with repositories for storage and services to manipulate them before storage.

I'm trying to reconcile how I used to do things with the "right" way to do them in MVC, if there is any one such way. The thing I'm getting hung up over right now is when to use ViewModels versus when to use my domain objects that are in a whole other project. Validation is done with ViewModels, but as I write more customized, business-logic validation, it seems like it's too much responsibility on a lowly ViewModel that was just there to help me move data around before storing it officially in the database through the repository layer.

I'm also getting tired of mapping ViewModel data to the "official" domain object that the repository stores and retrieves, but I feel like I shouldn't tarnish my domain objects with the MVC attributes for validation, either.

Do you have any advice for where to draw the line between domain objects and mere ViewModels? Or am I complicating things, and my ViewModels should actually be the "official" models that the repository stores?

tereško
  • 58,060
  • 25
  • 98
  • 150
Chris
  • 4,030
  • 4
  • 47
  • 76

6 Answers6

15

Do you have any advice for where to draw the line between domain objects and mere ViewModels?

Personally I always use View Models. All UI validation logic is done on the view models (required fields, ...) and business logic on the domain models (username already exists, ...). I also use AutoMapper in order to not get tired of mapping between the domain models and the view models that are passed to the view.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 1
    What do you do when you want to `only` display information from a `list` of domain objects? Do you just put the objects in a view model? – Omar Mar 09 '11 at 16:32
  • @Omar, I define a view model corresponding to the element type of the list and then a mapping between this view model and the model and finally ask AutoMapper to map lists (it does this automatically) and pass a list of view models to the view. But if I needed some other properties I would have another view model which itself would have a list of view models. – Darin Dimitrov Mar 09 '11 at 16:34
  • 1
    For truly read-only views (no way of "switching" to an edit mode), I generally use my domain models for that as view models really don't buy you much at that point. – Brian Ball Mar 09 '11 at 16:42
  • 2
    @Brian Ball - I disagree - what about databinding issues for display, view models allow you to stringify which makes the code in the view simple. – Rob West Mar 09 '11 at 16:57
  • I find that my domain objects are always exact copies of their read-only view model counterparts. It's tedious and redundant to create another class which only has a different name than your domain object. It's rare that I need to do some very cumbersome manipulation to get a valid read-only property from my domain objects. – Omar Mar 09 '11 at 17:01
  • 3
    @Omar, in the applications I am developing it might happen that the view models are exact copies of their domain objects but that's extremely rare. I usually have Display attributes on my view models that will format the labels being displayed, localize them, produce proper formatting of decimals, ... – Darin Dimitrov Mar 09 '11 at 17:03
  • @Darin - Good point. Completely forgot about display attributes and localization. – Omar Mar 09 '11 at 17:04
7

I think the best approach is to use view models ALWAYS. These are about presentation concerns and should be where basic input validation is handled. Domain objects are not appropriate for this.

I use specific view models per view and only include the information that is needed in the view - keeping view models totally view-centric makes for nice clean views.

You can use Automapper to help remove the drudgery of moving between view and domain models.

Can I recommend ASP.NET MVC 2 in Action as a great book for strong ASP.NET MVC patterns. This covers using Automapper in detail.

Rob West
  • 5,189
  • 1
  • 27
  • 42
7

I generally default to using View Models, though for read-only views, I have been known to use the domain model (no reason to go through the overhead of mapping if I am only going to read data out of it).

If you do decide to use domain models, I would never let MVC bind directly to them, because if someone knows your domain well enough, they can post values that bind to properties you do not want the user to be able to edit. You can define white and black list of properties of what model binder can and cannot bind to, but utilizing that is something else you'll have to maintain and something that can easily be forgotten about.

Brian Ball
  • 12,268
  • 3
  • 40
  • 51
  • Good point about the malicious binding problem. Nowadays there is also the [BindAttribute](http://msdn.microsoft.com/en-us/library/system.web.mvc.bindattribute%28v=vs.118%29.aspx) available. – Oskar Lindberg Dec 05 '14 at 13:20
1

Domain models and ViewModels will look very much like each other. However, ViewModels usually contain view logic attributes and properties. Also sometimes data type can be different, for example you might need to define a DateTime property as string just get the validation working without raising any errors.

I am using AutoMapper to convert from Model to ViewModels/vice versa.

Aliostad
  • 80,612
  • 21
  • 160
  • 208
1

ViewModel are good but don't forget Validation attributes are not only limited to MVC projects, you can use them in any .net project. Because of this it can make sense to apply the validation attributes to your domain objects, preferably by using a partial class and/or a Validator class http://weblogs.asp.net/scottgu/archive/2010/12/10/class-level-model-validation-with-ef-code-first-and-asp-net-mvc-3.aspx

longhairedsi
  • 3,133
  • 2
  • 28
  • 28
1

My approach is that a ViewModel model should be associated to a single view (or least a set of related views), and is usually a sub-set of your domain model. I see a ViewModel as responsible for UI validation, where as your domain object is responsible for business rule validation.

As for mapping between the two, highly recommend using Automapper which can automatically map properties based on conventions, it's a huge time saver.

JonoW
  • 14,029
  • 3
  • 33
  • 31