views:

114

answers:

4

Assuming you wanted to develop your Controllers so that you use a ViewModel to contain data for the Views you render, should all data be contained within the ViewModel? What conditions would it be ok to bypass the ViewModel?

The reason I ask is I'm in a position where some of the code is using ViewData and some is using the ViewModel. I want to distribute a set of guidelines in the team on when it's right to use the ViewData, and when it's just taking shortcuts. I would like opinions from other developers who have dealt with this so that I know my guidelines aren't just me being biased.

+2  A: 

I personally never use ViewData, everything goes through the Model, except when im testing something and i quickly need to be able to see the value on the view. Strongtyping!

Fabian
I agree completely. Magic strings are at best ugly, and at worst trouble. That said, I also use the ViewData to quickly test stuff, but the problem is when that ends up as the permanent solution!
DaveDev
Yep - 100% agree. I would prefer if that could even be deprecated.
Pure.Krome
@Pure.Krome: You could certainly emulate depreciation using the method described in my post. Overriding the viewdata property in a base controller and adding the [Obsolete()] attribute would give you the same result (essentially).
DanP
+5  A: 

Just to further Fabian's comment; you can explicitly ensure viewdata is never used by following the steps outlined in this article. There's really no excuse not to use models for everything.

If you have no choice but to use ViewData (say on an existing project); at the very least use string constants to resolve the names to avoid using 'magic strings'. Something along the lines of: ViewData[ViewDataKeys.MyKey] = myvalue; Infact, I use this for just about anything that needs to be "string-based" (Session Keys, Cache Keys, VaryByCustom output cache keys, etc).

DanP
+1 - we always use stongly type viewmodels here but do use viewdata for small bits of additonal 'trim'. this usually ONLY occurs for us in partial views that are reused in a variety of places.
jim
@jim: Agreed, there are scenarios (like shared partial views) where this is unavoidable; so best to take measures to prevent shooting yourself in the foot when you need to fallback on using ViewData :)
DanP
@DanP - What do you mean about string constants vs magic strings, and why is using ViewData in shared partial views unavoidable?
Howiecamp
@Howiecamp: A string constant is at the very least *strongly typed*; so they should always be preferred to using a string literal for accessing dictionary data (this also gives you a nice 'registry' of the keys in one fixed location as well). In regards to ViewData usage being 'unavoidable', that isn't completely accurate - but it is sometimes the best alternative to trying to create some sort of base 'god' model to handle all cases. Hope that helps to clear up some of my comments :)
DanP
+1  A: 

In terms of ASP.NET MVC 2, ViewModel pattern is the preferred approach. The approach takes full advantage of compile time static type checking. This in combination with compiling mvc views will make your development work-flow much faster and more productive since errors are detected during build/compile time as opposed to run time.

Bikal Gurung
A: 

One approach you may wish to consider as your views become more complex, is to reserve the use of Models for input fields, and use ViewData to support anything else the View needs to render.

There are at least a couple of arguments to support this:

  1. You have a master-page that requires some data to be present (e.g. something like the StackOverflow user information in the header). Applying a site-wide ActionFilter makes it easy to populate this information in ViewData after every action. To put it in model would require that every other Model in the site then inherit from a base Model (this may not seem bad initially, but it can become complicated quickly).

  2. When you are validating a posted form, if there are validation errors you are probably going to want to rebind the model (with the invalid fields) back to the view and display validation messages. This is fine, as data in input fields is posted back and will be bound to the model, but what about any other data your view requires to be re-populated? (e.g. drop-down list values, information messages, etc) These will not be posted back, and it can become messy re-populating these onto the model "around" the posted-back input values. It is often simpler to have a method which populates the ViewData with the..view data.

In my experience I have found this approach works well.

And, in MVC3, the dynamic ViewModels means no more string-indexing!

MJ Richardson