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.
Related
First of all, I have been a php programmer for a long time and I am a mvc programmer newly. I did a few minor web sites that each have one or two controller at most. But I've started a website that will be very major web site. There will be a lot of data to pass to views.
Now, normally I try to use model approach every time instead of ViewBag or ViewData approach. If the view demands more data, then I change the model class and then recompile the project. Especially, if the topic is an index page, the data to pass to the index's view changes every time. In a big web site, I'll use a lot of partial view that uses different models. So every time, I will have to change the index's model to support those partial views in the index view. if I add a new partial view into index view, I have to add the partial's model into the index's model.
I implement an IndexModel class for an index view every time when I start a website. Then I add properties to this model every time when I add a new partial view to the index.
Now is this a correct approach or should I use ViewBag or ViewData for partials' models. I think the real question is when we should use the model approach and when we shouldn't...
If you share your experiences, I would be grateful.
The MVC approach you should use always, especially for simple sites, it's save your time and make application more understandable.
If you write something larger than two pages, you need to use MVVM pattern (growth of MVC), in that case you will escape from using "partial models" with ViewModels.
Model must contain only busines logic.
Be better if you will always use ViewModel (not a Model) for returning data from a view and pass it to view, because it provides some safety.
For facilitate the procedure of copy data from Models to ViewModels use the things like AutoMaper and EmitMapper.
ViewBag and ViewData you should use only for additional data's like item colections for DropDown, or some view-text like page title.
One more advantage of MVVM pattern is better testability. If you write and support really hugh site you may write tests for some responsible parts of code.
For more details you can look at google - MVVM, ASP-MVC.
If i something not understad in you question or miss, write it in the comment ("add comment" ref).
I personally prefer to keep my sites consistant and always use Model + Viewmodel (no matter how big the site is) despite the extra work (which isn't much anyway).
It helps with maintainability. I know where and how everything is stored and coded into the site.
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).
I have a question regarding keeping the controller and view separate. It seems to me that the controller should only pass a model to the view, and the view decides how to display the model. This way, the controller and model stay separate and can be independently developed. However, a lot of tutorials I see online and even in the book Pro ASP.NET MVC Framework, I see a lot of examples using either ViewData["string"] or TempData["string"].
Doesn't this introduce two problems? The first one is that the view is now somewhat coupled to the controller in that it has to know the name of the strings that the controller is setting in ViewData/TempData. The second is that these are loosely-typed, meaning there's no Intellisense. If I was developing the controller, I can't just tell another developer working on the view to just use Intellisense for the model, I'd have to give him the name of the strings, and if I ever change the string names, I'd also have to change it in the view.
I guess ultimately what I'm asking is, is this right? Or am I not understanding something?
View Data is one of the a way to pass information between the view and the controller but, as you said, there's no intellisence and it increase coupling. Instead, you should consider using a ViewModel. See Scott Gu NerdDinner example (freely available) about the way to use ViewModel and about the pros and cons of ViewDate vs ViewModel.
I hope it will help.
I think that the tutorials and book are using this method to try and make things a little easier to start out. However, I my opinion is that this might be starting some bad habits as you suggest.
The way I do it roughly based upon this article by Jimmy Bogard:
All views are strongly-typed
One specific ViewModel class per View
The View determines what data is in the ViewModel
I don't use the Auto-Mapper as he does though. I usually use a utility method to convert my Model object to the associated ViewModel object.
Yes you are right, it's considered best practice to create a class often called ViewModel that is being sent to/used in the View. The ViewModel usually contains the model as well as any other data the view might need, such as page number for a paginated list view, or values for a list for the view to display.
I'm an ASP.NET MVC newbie, but have used many Model-View-Controller frameworks previously.
I recently came across the convention of gathering up the pieces of data that your particular view needs (indeed, it's assigned to the ViewData) into a new class called (NameOfView)ViewModel.
Gathering up this data so that it's associated with the functions provided by the View/Controller interaction strikes me as a helper struct, or even closure mechanism (in the 'encapsulates a collection of variables' sense).
So why is it called 'ViewModel', given that it's neither a View or Model?
Does anyone else find the name confusing?
EDIT: What's wrong with just putting properties onto the View so that the Controller can populate them (as in other MVC frameworks)?
In my reading on this topic I've come across a variety of arguments as to why a developer would or would not want to use a ViewModel. Some even argue that a ViewModel should never expose anything more than strings. At this point I am not that extreme in my thinking. I will agree however, that it is not a good idea to expose Domain/Core Objects to the view. After some first hand experience it feels cleaner to remove this dependency.
While I don't agree with everything below Daniel Root makes a pretty good case for a ViewModel:
Most MVC examples show directly using
a model class, such as a LINQ-to-SQL
or Entity Framework class. The Visual
Studio wiring for MVC even steers you
into this concept with it's default
"Add View" code-generation, which lets
you quickly gen up views based on a
single model class. However, in
real-world-apps you often need more
than just a single table's data to
build out a page. Some examples get
around this by stuffing secondary data
into ViewData, but a better way to do
this is to create a "roll-up" class to
contain properties for everything
your view will need. This has the
added benefits of being more
strongly-typed, supporting
intellisense, being testable, and
defining exactly what a view needs.
Jeff Handley gives a nice description of the ViewModel pattern which he argues can be used in conjunction with MVC.
Edit
I've recently brought my thinking in line with Jimmy Bogard's regarding view models. After a fair amount of pain with each implementation I've tried having one view model per view creates a much cleaner development experience.
The model is a view-agnostic representation of the data. The view model is a view-specific representation of the data: it's the model as it might appear from a given viewpoint.
Consider a model that consists of raw data points; a histogram view might then have a view model consisting of a set of buckets and totals drawn from that data.
Logically, it's a subset or transformation of the model - it could be generated on-demand with a view-specific function and the model as its only input.
Regarding properties on the view vs. a property bag or custom object... I'm sure someone has strong feelings on this, but personally I don't see the big difference. You're producing a view-specific representation of the model and passing it somehow; the exact mechanism doesn't seem all that important.
Re: why can't the controller populate properties on the view?
Because the view doesn't exist at the time the controller action is executing. The idea behind returning an ActionResult from your action is that something later in the processing pipeline will evaluate the result and determine the best course of action (perhaps rendering a view, or maybe selecting a view to match the request (like special views made for mobile devices)).
I did a view posts on selecting the right kind of model object here: Putting the M in MVC Part I, Part II, Part III.
And yes, the term "ViewModel" term is en vogue right now, but it is in the spirit the original MVC adopters had in mind.
This isn't actually an answer but I highly recommend you watch the MVC2 Basics video by Scott Hanselman. It explains everything, and even though I have done ASP.NET MVC before it made a lot of things clear for me.
Its here: http://channel9.msdn.com/Blogs/matthijs/ASPNET-MVC-2-Basics-Introduction-by-Scott-Hanselman
It's called that because it's a "Model made for a View". I understand why the choice of term is a bit confusing.
It's a helpful approach if you don't want all your data passed to the view as a big hash array. It gives you a strongly-typed class dedicated to the UI, which pollutes neither the core Model or the View. It also allows you to encapsulate UI logic -- views should be kept dumb.