Question

I have only been working with the MVC framework (ASP.NET MVC2/3/Razor) for a few months now and I am really enjoying it, however I am having a hard time figuring out a standard for View Models. In my projects, I have a Models folder (Contains my data models - Linq DBML, Repository[ies], Extension methods) and a Models/ViewModels folder. My view models are usually reusable classes which usually just contain simple get/set properties for the LINQ objects or collections of objects I need to access for a particular view.

Now the problem I am having is figuring out when to create a view model. My goal is to use the LINQ object as the view model as often as possible, especially when it is an Edit action. My problem is what if I have other bits of data that I might want to use for display purposes only? I don't like to use the ViewData/ViewBag collections, as accessing members of these requires knowledge of the collection item's key (not easy for a designer/front-end guy to "guess"). I also don't like the idea of creating a ViewModel for each View, as it seems like unnecessarily messy code.

For example, imagine I have a data model for an Employee, and I want to display some information unrelated to that employee - say, site statistics, dynamic menus, and whatever else you can think of that might come from the database. What model should I pass the /Employee/Edit action? The Employee object with a bunch of ViewData[] for the rest, or a custom EmployeeView?

Is there a gold standard? What am I missing? What are you doing different that I should look into? Thanks in advance!

Was it helpful?

Solution

You've named three things here:

  • Site statistics
  • Dynamic menus
  • Whatever else [...] might come from the database

That third point is a trap; just because something is in your database, doesn't mean it's part of your domain model.

Navigation might be based on a database. It might also be be in a site map or hard-coded into the application. It's actually not application data, it's application configuration. If you're storing it in the application database, that's OK (well, not really), but it is not part of the model itself.

Similarly, site statistics usually are stored in a database, but they're stored in a different database, specifically an analytics database (and many people just "outsource" this to Google). So again, they are a kind of data, but they are not your model.

If you want your application to make sense, you need to separate these concerns at a conceptual level. Navigation gets done in your master page/layout, including whatever dynamic code is necessary to make it work. It is pure view logic - don't let it leak into your model. It's completely OK and usually preferable to use the ViewData/ViewBag for concerns that are ancillary to the actual feature that is currently in use.

Now, assuming there are other kinds of view data that actually are application data: It's true in principle that views are supposed to be connected directly to models - that is after all what "MVC" means - but in practice, it's just a re-implementation of the ill-conceived "canonical data model" idea. Domain and presentation are separate concerns, and as such, imply different contextual models - in the latter case, that's a View Model.

When I first started doing MVC work, I was reluctant to use view models as well. But after I became more accustomed to the idea, I realized that it was really the only tenable solution - especially when your "model" is mostly a thin wrapper over the database itself. Views and data change in different ways and at different rates; if you don't want to be worrying about a constant stream of bugs and regressions then you need some insulation between the two. Build a mapping layer and call it a day.

At this point I've taken to creating a different view model for every view, whether I think I need it or not. At the beginning, it might be nothing but a carbon copy of a model class, but it means I can tweak it at any time and in any manner without having to screw around with the underlying model - and vice versa. As tv says, the initial view model is trivially easy to generate with AutoMapper, and will take up maybe 30 seconds of your time.

Just use view models, and hope that eventually the tools support view-model auto-generation.

OTHER TIPS

I never use my entity classes directly as view models. I always create a view-specific model for each view containing the data for that view. I've started using AutoMapper to map between view models and entity models. I mediate this through a ModelMapper class that has a ToViewModel<TEntity,TViewModel>() method for handing standard mappings (just invokes the automapper) and specialized mapping methods for custom mappings, especially to support creating and updating entities from view models.

If You create page for editing employee but You also display things You mentioned (site statistics/menus) why not put them in partial views or layout files?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top