The initial situation is that I map my domain model into a presentation model.
I have to display an update/create formular with textboxes and a dropdownlist.
Should the viewmodel contain a list for the dropdownlist or should I pass the data for the dropdownlist by using ViewData?
When should I use ViewData and when should I not use it?
Shall input fields like dropdownlists have a seperate view model?
I tend to try and use ViewData as little as possible since you always need to cast values, you need to do error checking for nulls or for keys that don't exist and it clutters the views in my opinion.
I tend to try and use viewmodels whenever possible since I find strongly typing the view to the model as a cleaner approach.
I would put as much of the data into the viewmodel as possible, but only what makes sense. For data that shouldn't belong in the viewmodel I would pass in as ViewData, but would try to keep the amount to a minimum.
As far as you question goes for input fields, if they are all related I would make a ViewModel for that instead of passing in 5 or 10 pieces of data in the ViewData since logically grouping them in one place would make sense. It really is a matter of preference, but I found this approach to be the best for me.
It's personal choice really. The disadvantage of ViewData is that it's weakly typed and requires casting.
You might want to take a look at NerdDinner, in particular the DinnerFormViewModel and the list of countries to choose from. Basically, they have a Dinner model (used for the index view, where they need a collection) plus a DinnerFormViewModel which contains a single Dinner instance and a SelectList for the countries. The create view (aptly named DinnerForm) is, of course, strongly typed and takes a DinnerFormViewModel.
I found something very interesting here ... http://weblogs.asp.net/rashid/archive/2009/11/27/extending-asp-net-mvc-2-templates.aspx
Exactly what I need.
You should pass the list as part of your Model. Or, if the list is pretty pervasive (like, say, a list of States or a Yes/No list), you can create a static list in a static class that can be referenced directly in your ViewPage. I don't see why you'd want to pass it via ViewData, as you'd have to cast your list in your ViewPage.
Related
In an ideal 'hello world' one should pass a strongly typed model back to the view.
return View(MyModel);
If things get sticky, we can create a
ViewModel
return View(MyViewModel);
ex.
MyViewModel
MyModel
Foo
I can avoid creating the whole ViewModel
and use a ViewBag in part.
ViewBag.Foo = Foo;
return View(MyModel);
I realize I will lose some strongly typed functionality
(ex. Intellisense)
in my View for that ViewBag.
Is this approach sloppy? against what MVC stands for?
If so, what is really the point of ViewBag?
The most useful use-case that I know of is out-of-band data like a message that might be shown on every page. An action filter could add that message to the ViewBag conditionally. You probably don't want to modify every view model class to hold that unrelated message because it might be a cross-cutting concern. An example of such a message/widget would be Stack Overflows outage announcements.
I do not recommend using ViewBag instead of a view model. The model class approach has the typical static typing advantages at the small cost of writing a class.
This is a good question, personally, I don't really think there is any point - all it does is encourage "lazy" coding. dynamic objects have their uses, however, I don't see the ViewBag as being one of them, I would much rather use ViewData[]/ViewModel and get my type-safety in there, especially when I know what types I am dealing with.
I haven't encountered a scenario where it was beneficial to use ViewBag over the alternative (a correctly structured view model). Some of the other answers mention using it for a piece of data that needs to be displayed on every page. In this scenario you should create a base ViewModel class that all of your ViewModels inherit from. I use this structure to store the logged in user, etc.
In my opinion ViewBag serves one purpose: to make it easy and quick to give a product demo of ASP.NET MVC while writing minimal code. It is not the best way to structure code, but it sells the product.
A month or two ago when I started doing asp.net MVC work I remember reading that it is not recommended to call object methods like the following in the view:
<%: Html.ListBoxFor( m => Model.SelectedId, Model.SelectItems.ToSelectList() ) %>
That above is just an example, not a direct line of code I am using. I am using extension methods to turn my enumerables into ListBox binding-ready IEnumerable collections. I know there was a concern that someone had raised in an article about this, but I cannot remember what it was. I am not actually coding it this was at the moment, but the way I am doing it is becoming a burden. I am writing extension methods to convert all of my IEnumerable objects into both SelectListItem collections and now a MultiSelectList object. So my view models are becoming bloated with "potential" ways of displaying the data. Instead of their just being an enumerable of available options, I am tracking 4 new pieces of data: SelectListItem collection, SelectListValue object, MultiSelectList control, MultiSelectListValues collection.
I am not opposed to keep going about this, but I would like to remember why it was recommend not to call the extension method on the View if I'm using strongly-typed full/partial views. I tried to find that article and others like it but I could not. I wish my memory was better than this, but hopefully someone out there knows this offhand and would be willing to share it with me!
Thanks in advance!
The idea your talking about is based on a principal that the view in MVC should be as simple as possible. Because it is the most difficult to test unnecessary bloat should be avoided.
Your example line could be paired down a few different ways. You could try writing an extension that takes the enumeration from your model and converts it to a select list that can be fed into a listbox, or you can change the model's property to return an enumeration of list items. The later is my preferred method. The model exists to organize the data to be consumed by the view so theres no reason to have it output data that cannot be consumed by the view directly. Either one of these methods would take complexity out of the view and place it somewhere that is easier to unit test.
Hope this helps.
This might be similar to ASP.NET MVC - Populate Commonly Used Dropdownlists.
I want to populate DropDownLists. Some of it is static data. Some of it comes from the Database. A couple of times I found myself forgetting to call the code that populates my lists and sets the ViewBag accordingly. It is almost worth adding a unit test for this. The only way I think that this suits a unit test is if you place it in model/service. Is there a best practice for this kind of thing?
I'd suggest that the data is contained within the model but is perhaps constructed by a html.helper method. this way, you keep the plumbing markup out of the view and leave the controller free to invoke the neccesary view and model.
You could also of course hand it off to a partialview with an <IList<SelectList>> model.
cats and their skin :)
If you follow the spirit of the pattern then the Model should supply the View with everything it needs to present to the user that's not static. If you have static dropdown lists then you could say that these could be constructed within the mark-up. If you are passing a SelectList to the View from your Action then I'd stick it in the Model to make things simpler and more coherent.
My rule of thumb is that the data must somehow be in the model, either as a ready to use SelectList or at worst in some container that can easily be turned into a SelectList using a LINQ-to-object call.
The bottom line is that the view should never contain any non trivial code.
EDIT (answer to your comment):
I try not to put too much code in models. Models are more like a simple bunch of data gathered by the controller and used by the view.
Regarding simple and/or common things such as the days of week, I believe an HTML helper is the most elegant solution. See WayneC's answer in this question.
I am wondering if it is a good idea or bad, placing things like a List of countries in ViewModel, for binding to a drop down list? For example on a site's Registration page.
I was under the impression that a ViewModel is supposed to represent an instance of the filled out form, but I think I may be wrong as I have seen other people put things like lists in their ViewModel.
Would it not be better to put it in a static class somewhere and called directly from the View?
Like CommonData.ListCountries(); and then using Lambda to convert to SelectList item list in the view Directly?
As you've realized there are a variety of ways to accomplish your goal. While the MVC design pattern encourages certain application organizations how you organize your models, views and controllers is ultimately a matter of preference.
Scott Allen discusses his preference for dealing with ASP.NET MVC drop down lists in a blog post. Scott uses an extension method to convert an enumerable of a complex type into an IEnumerable<SelectListItem> on his model. He then describes that upon post back ASP.NET MVC will not be returning the IEnumerable<SelectListItem> he sent to the view, but only the value the user selected. He then suggests that utilizing two models can simplify things.
This is a reasonable description of what I refer to as ViewModels and FormModels. A ViewModel carries the display data to the view and a FormModel is used for carrying collected data back to a controller action. To explain further:
ViewModels contain data that help render views. By organizing my ViewModels this way I can place all necessary information to render a particular view into an associated model. This prevents me from having to use ViewData for anything that's not truly temporary.
FormModels are used to gather user input. FormModels (almost) never contain references to other complex types and are made up of primitives, DateTimes, and strings.
In either case I have a hard rule to never reuse a model for a different view. Having your models closely aligned with the views used to render them makes your views easier to write. You don't have to worry about things like static methods because your models should be carrying data to their associated views in a form that is easy for them to render. Tools like AutoMapper can help "flatten" domain objects into models for display purposes.
For additional reading checkout: ASP.NET MVC terminology is tripping me up - why 'ViewModel'?
Whatever data your View needs, put it in the ViewModel.
The way i see it, once your view is going through the rendering process, it should have all the info it needs from the Model it is bound to.
If you start to use helper methods, then the View is "going back to the controller" in a sense. Extension/helper methods are fine for formatting, etc, but they should not call through the model.
Don't forget, you also have ViewData (basically HttpContext.Current.Items, lives for single request), which is a lightweight storage mechanism that can be used to share data across partial views (for example).
In ASP.NET MVC it's possible to choice between having a typed view were you define in the codebehind what kind of data the view can should expect. But it's also possible to not define this and just pass any kind of data to view in a ViewData container.
What would the best model here or should I mix depending on what kind of data we're talking about (maybe just make sure to have data that's critical to the functionality of the view typed and other data not typed?)? I don't really understand why there is a option here ...
I would recommend always using the strongly typed ViewData... that way you have compile time checking, intellisense, you don't have to do casting in your view, and the ability to refactor your code much easier.
Earlier releases of the framework required you to choose between a ViewData dictionary and strongly typed view model.
Now you can mix the two. Combine this with some of the new features of Preview 5, such as ModelState, validation, and auto-binding to form fields and it becomes more compelling to use the ViewPage for the main model in your view being rendered.
You can still add data to the dictionary in the controller pipeline and request it later on using ViewData["key"] ... or even better ViewData.Get("key") from MvcContrib.
I had this thought too in the past. In my site, I used to strong-type the view, when the view is almost a 1:1 model of the class you are showing. Like showing a list of all users, I type to List, this way I don't need to cast anytime to have the right datatype.
In none specific views, I just strong-type to the most "heavy"/used type.
In forms, the form itself is the type of the view when returning View(form); ....