0

I plan to create a Asp.Net MVC app which contains edit/create pages for a large model with many-to-many relationship with other models. I found the Saving Many to Many relationship data on MVC Create view and plan to use it.

In the example, the create page uses the following ViewModel.

public class UserProfileViewModel
{
    public int UserProfileID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<AssignedCourseData> Courses { get; set; }
}

And the UserProfile model has only two properties so the ViewModel just duplicates all the properties.

public class UserProfile
{
    public UserProfile()
    {
        Courses = new List<Course>();
    }
    public int UserProfileID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Course> Courses { get; set; }
}

However, in my case, there will be a lot of properties (with data annotations), say 50 properties. Should the ViewModel duplicate all these properties (with data annotations too)? (looks ugly?) Or is there a better way?

Update Is it a good practice to define ViewModel as

public class UserProfileViewModel
{
    public UserProfile UserProfile { get; set; } 
    .... // Other properties needed by the view.
}

One shortcoming of this way is it expose all the properties in the Model even it's not needed in the view.

Community
  • 1
  • 1
ca9163d9
  • 27,283
  • 64
  • 210
  • 413

2 Answers2

2

The thing with View Models is very simple: the View Model should consist only from data needed by the View. That is, the view model design is driven by the (static) view. Static because you can updates parts of the view via ajax in the browser so it makes no sense for your model to contain that info (except if it's required as init values for the JavaScript).

How the data is stored or how it's used by the business layer (if any) is not the view model concern.

Updated

The cleanest and safest way is to define the view models with the properties you need (you can copy paste them from the other model it's ok in this scenario) then use AutoMapper to map the business object to the view model. This way you can evolve both models differently. Personally, very rarely my view model is identical to a business model, they resembles a lot but there those tiny differences that complicate the things.

From a Separation of Concerns point of view, the busines model is for business usages, persistence model is for persistence usage while view model is for the view usage. Don't mix them or you'll have one model serving too many masters, which leads to complications down the road.

Igor Popov
  • 9,795
  • 7
  • 55
  • 68
MikeSW
  • 16,140
  • 3
  • 39
  • 53
  • I understand the purpose of VM. Just feel like a lot of code are duplicated (especially for these business model with a lot of properties). It seems like something wrong. – ca9163d9 Jan 19 '14 at 08:26
  • The duplication is ok in this case. Wrong would be to reuse the same model for different concerns (outside its original layer/bounded context) – MikeSW Jan 19 '14 at 09:56
1

Taken from: This excellent explanation of ViewBag, ViewData and TempData

The type of data that suits ViewModels well is as follows:

  • Master-detail data
  • Larger sets of data
  • Complex relational data
  • Reporting and aggregate data
  • Dashboards
  • Data from disparate sources

So in summary, yes the ViewModel is what to use when the view requires a lot of complexity, it suits your needs. As for using and populating every property that should be determined by what the particular view requires. ViewModels are not necessarily one to one representations of a model / entity. That should be dictated by your view requirements, e.g. UserCourseViewModel could aggregate the UserProfile and Course entities, but not necessarily all of both of their properties, unless of course all properties are required by the view.

Rachels summary:

The ViewData and ViewBag objects give you ways to access those extra pieces of data that go alongside your model, however for more complex data, you can move up to the ViewModel. TempData, on the other hand, is geared specifically for working with data on HTTP redirects, so remember to be cautious when using TempData.

Paul Zahra
  • 9,522
  • 8
  • 54
  • 76
  • I'm of opinion that you should always use the strongly typed view model for the view data. ViewData/ViewBag are legacy hacks. All info required by the view should be in the view model. I know about page.title using the ViewBag, but it's too unimportant to think about a proper alternative. – MikeSW Jan 18 '14 at 10:16
  • I've updated the question and ask if it's a good idea to just define a property of the type of Model? – ca9163d9 Jan 18 '14 at 10:21
  • The ViewModel should contain only the properties of a Model that are used in the View... generally speaking unless we are talking 50 Model properties, 49 of which are required by the View, in which case I would just include the UserProfile as you have done in your example even though it's not technically correct. – Paul Zahra Jan 18 '14 at 10:28
  • Have a look at this helpful SO post about SoC: http://stackoverflow.com/questions/1605735/asp-net-mvc-model-and-viewmodel-separation-of-concerns – Paul Zahra Jan 18 '14 at 10:32
  • If the View requires 49 properties, that's a sign of a problem – MikeSW Jan 18 '14 at 11:04
  • Lol, indeed, it's just an example as the OP in their example uses 50... as an example :D – Paul Zahra Jan 18 '14 at 11:08
  • @MikeSW The Edit/Create view need to fill or edit, saying, 45 properties of the properties. Isn't it quit normal? – ca9163d9 Jan 18 '14 at 21:26
  • I don't really count the number of properties on a view model, I just put in it what the view needs it and that's it – MikeSW Jan 18 '14 at 21:29