2012-03-30 77 views
1

我已经开始使用MVC 3,我非常喜欢使用它。在许多层面上,这比WebForms更好的体验。ViewBag中的对象

但是我有一个关于ViewBag(新ViewData)的问题 我非常小心地坚持声音建模实践,我倾向于将视图需要的所有东西放到ViewModels中。然而,就ViewBag而言,除了糟糕的建模实践之外,是否还有其他顾虑,表明应该谨慎使用ViewBag?我自己并没有太多的使用它,但是队友今天提出了这个问题,我只能推荐限制它的使用,因为它是一个弱类型模型,被动态地使用动态(sudo类型)

我可以告诉那里使用它不应该有任何性能影响? 我对不对?这只是另一个应用于视图服务器端的对象。 我不指望使用动态的任何性能影响(如果有一个可以测量的)

对于使用ViewBag的缺点(甚至是优点),您有什么看法?

回答

2

对我来说,最大的问题是ViewBag不是类型安全的,如果你不小心的话,很容易产生运行时错误。

视图包真的只是一个方便,以防止简单的情况下,否则你需要一个新的视图模型。我经常使用它们,但仅限于非常简单的数据。

+0

是的,我同意,这似乎很像一个好地方到另一个地方追悔没来,当你做你的视图模型,或者没有适合。我通常将它用于简单的事情,如int或其他一些简单的对象。 – TGH 2012-03-30 04:37:24

0

从我的文章在: http://completedevelopment.blogspot.com/2011/12/stop-using-viewbag-in-most-places.html

 
Even the built in templates give us support for ViewBag. The scaffolding templates create ViewBag.SomeEnumerable to use for our pages. 
Sure - its quick code and since it's auto-generated will likely work ok. The problem comes in from the fact that ViewBag is a dynamic object. There are no compile time type checks. If you misspell something you won't be notified from the compiler. 

I've seen this used in such bad ways, I would love to see it's usage curbed and applications cleaned up. 

So in a controller: 
ViewBag.SomeProperty = "10" 
and in the view: 
@ViewBag.Som3Pr0p3rty 
We won't ever know of this error. It won't even generate a runtime error since the misspelled name just generated a null. 


Use ViewModels and save yourself from these potential problems. Our templates set a page title in ViewBag as well. 


There are several options in setting a page title. Since this is a well known property one could argue that using it just for Title is ok. I wouldn't argue this. There are other options. 
1. Set it in a section in the layout and render it from the client. 
2. Use ViewBag.Title 
3. Use a filter (seems much too complicated for a title) 
4. Use a Model.Title field. 

Since by default we have a ViewBag.Title field created and our templates also get it by default, I'll yield that in this case, its ok. 

What about select lists? 
Rather than the default 

ViewBag.CustomerId = new SelectList(db.Customers, "CustomerId", "FirstName", order.CustomerId); 


Do something like 
yourViewModel.Customers = customers; //a loaded collection 

and in your view 
@Html.DropDownListFor(x => x.CustomerId, new SelectList(Model.Customers, "CustomerId", "Name")) 

Or if you prefer to set your ViewModel to contain the SelectList 


yourViewModel.Customers = new SelectList(db.Customers, "CustomerId", "Name", order.CustomerId); 

and now your view would be slightly cleaner as: 
@Html.DropDownListFor(x => x.CustomerId, x.Customers) 

See, that's not so difficult now is it? Enjoy!