Why do we use ViewModels?

For smaller projects, you’re right. I hear your argument and sympathise – however there are good reasons for this, drudged and repetitive work, especially in larger and more complicated applications:

  • It’s essential to perform all processing within the Controller’s action. However in the example you’ve given, the Repository.Get method might return a lazily-evaluated IQueryable object, which would mean the DB wouldn’t be hit until the View is evaluated. For a variety of reasons this is bad. (A workaround is to call .ToList while still in the controller).
  • “A view should not contain any non-presentational logic” and “You should not trust the View” (because a View could be user-provided). By providing a Model object (potentially still connected to an active DatabaseContext) a view can make malicious changes to your database.
  • A View’s data-to-display does not always map 1:1 with its Model’s data, for example consider a User Details page:

    A User’s EF Model object represents its entity in the database, so it probably looks like this: User { UserId, UserName, PasswordHash, PasswordSalt, EmailAddress, CreatedDate }, whereas the fields on a “User details” page are going to be User { UserId, UserName, Password, ConfirmYourPassword, EmailAddress }, do you see the difference? Ergo, you cannot use the EF User model as the view model, you have to use a separate class.

  • The dangers of model manipulation: if you let ASP.NET MVC (or any other framework) do the model binding to the incoming HTTP POST Request then (taking the User details example above), a user could reset anyone’s password by faking the UserId property value. ASP.NET will rewrite that value during binding and unless you specifically sanitize it (which will be just as drudgeful as making individual ViewModels anyway) then this vulnerability will remain.

  • In projects with multiple developers working in a team situation, is is important that everything is consistent. It is not consistent to have some pages using bespoke ViewModels but other pages using EF Models because the team does not share a concious mind, things have to be documented and generally make-sense. For the same reason a single developer can get away without putting excessive XML documentation in his source code, but in a team situation you’ll fall apart if you don’t.

There is a slight workaround in your case I’ll share with you, but please note the preconditions:

  • Your views can be fully trusted
  • Your views contain only presentational logic
  • Your application is largely CRUD
  • Your views correspond 1:1 with each EF entity model (i.e. no JOINs)
  • Your views only deal with single Simple models for POST forms, not Complex models (i.e. an object graph)

…then you can do this:

  • Put all one-way, non-form-related data into your ViewData collection, or the ViewBag in MVC 4 (or even a generic ViewData<T> if you’re hardcore). This is useful for storing HTML page titles and sharing data with Master pages.
  • Use your fully-evaluated and loaded EF models as your View<TModel> models.

But use this approach with caution because it can introduce inconsistency.

Leave a Comment