MVC ViewBag Best Practice [closed]
Asked Answered
D

11

33

For the ViewBag, I heard it was a no-no to use. I would assume have the content from the ViewBag should be incorporated into a view model?

Question:

  1. Is my assumption above the best practice. (Not to use a ViewBag and second to have it in the view model)

  2. Are there situations where a ViewBag is absolutely necessary?

Deemster answered 29/6, 2012 at 12:45 Comment(1)
From the perspective of Microsoft, We do not agree with never use ViewBag or ViewBag is a No No. Using ViewBag to pass model data is another matter and should be discouraged. Using ViewBag to pass meta-data (Select List) is fine. Pro MVC by Sanderson and other books use them and make no such definitive proclamations - 2. Abs necessary - I doubt it.Playpen
K
32

ViewBag is a dynamic dictionary. So when using ViewBag to transfer data between action methods and views, your compiler won't be able to catch if you make a typo in your code when trying to access the ViewBag item in your view. Your view will crash at run time :(

Generally it is a good idea to use a view model to transfer data between your action methods and views. view model is a simple POCO class which has properties specific to the view. So if you want to pass some additional data to view, Add a new property to your view model and use that.Strongly typed Views make the code cleaner and more easy to maintain. With this approach, you don't need to do explicit casting of your viewbag dictionary item to some types back and forth which you have to do with view bag.

public class ProductsForCategoryVm
{
  public string CategoryName { set;get; }
  public List<ProductVm> Products { set;get;}    
}
public class ProductVm
{
  public int Id {set;get;} 
  public string Name { set;get;}
}

And in your action method, create an object of this view model, load the properties and send that to the view.

public ActionResult Category(int id)
{
  var vm= new ProductsForCategoryVm();
  vm.CategoryName = "Books";
  vm.Products= new List<ProductVm> {
     new ProductVm { Id=1, Name="The Pragmatic Programmer" },
     new ProductVm { Id=2, Name="Clean Code" }
  }
  return View(vm);
}

And your view, which is strongly typed to the view model,

@model ProductsForCategoryVm
<h2>@Model.CategoryName</h2>
@foreach(var item in Model.Products)
{
    <p>@item.Name</p>
}

Dropdown data ?

A lot of tutorials/books has code samples which uses ViewBag for dropdown data. I personally still feel that ViewBag's should not be used for this. It should be a property of type List<SelectListItem> in your view model to pass the dropdown data. Here is a post with example code on how to do that.

Are there situations where a ViewBag is absolutely necessary?

There are some valid use cases where you can(not necessary) use ViewBag to send data. For example, you want to display something on your Layout page, you can use ViewBag for that. Another example is ViewBag.Title (for the page title) present in the default MVC template.

public ActionResult Create()
{
   ViewBag.AnnouncementForEditors="Be careful";
   return View();
}

And in the layout, you can read the ViewBag.AnnouncementForEditors

<body>
<h1>@ViewBag.AnnouncementForEditors</h1>
<div class="container body-content">
    @RenderBody()
</div>
</body>
Kyl answered 29/6, 2012 at 12:50 Comment(1)
The model is stored in the ViewBag, so it is always a necessity to have. Using a magic string may not be the peak of maintainability, but that aside all using a model does is enforce convention of declaring a type and a page variable.Laurence
L
32

1) Is my assumption above the best practice. (Not to use a ViewBag and second to have it in the view model)

You should use viewmodels instead of passing data via ViewBag as much as possible.

2) Are there situations where a ViewBag is absolutely necessary?

There is no situation where a ViewBag is absolutely necessary. However, there are some data I personally prefer using ViewBag instead of View Model. For example, when I need to populate a dropdown box for predefined values (i.e Cities), I use ViewBag for carrying SelectListItem array to view. I prefer not to pollute my ViewModels with this data.

Langlauf answered 29/6, 2012 at 13:31 Comment(4)
Excellent response in alignment with our (MS) published guidance. I would only change it from passing data to passing model data (meta-data excepted) See bottom of my tutorial asp.net/mvc/tutorials/javascript/…Playpen
@RickAndMSFT, I must admin I took advantage of your post when I first learned ViewBags. Great post by the way.Langlauf
Good answer, I also think using ViewBag instead polluting a viewmodel with a list of options to be passed to the view is a good practice. If a list is passed in the ViewModel it's because the list is likely to be edited or because it "makes sense" for the model. But in the case of a list of options where only one will be picked, ViewBag seems cleaner.Roadhouse
I think all the downsides to using dynamic typing is much worse than polluting the view model. You can't even look at the view and tell what is set in the view bag without reading through the entire controller.Perdition
C
5

1) Is my assumption above the best practice. (Not to use a ViewBag and second to have it in the view model)

Yes.

2) Are there situations where a ViewBag is absolutely necessary?

No. Everything that you have stored in a ViewBag could go into the view model passed to the view.

Cabrales answered 29/6, 2012 at 12:49 Comment(2)
What about meta-data? Should we yank out @ViewBag.Title from the templates?Playpen
Yeap, throw it away. Please. I don't wanna see in ASP.NET MVC 4. It makes me wanna vomit. Use it internally in the framework if you will but mark it as internal so that a developer never has to be confronted with it.Cabrales
L
4

The issue with ViewBags and the recommended best practice boils down to compile time checking. ViewBags are just dictionaries and with that you get 'magic' strings, so if you end up changing the object type of one of the viewbag items or the key name you won't know until runtime, even if you precompile the views using <MvcBuildViews>true</MvcBuildViews>.

Sticking to view models is best, even if you have to alter them to fit a specific view now and again.

Lakesha answered 29/6, 2012 at 12:54 Comment(0)
C
2

I have found some use for ViewBag where there is common functionality across all pages, and the functionality does not depend on the page being shown. For example, say you are building StackOverflow. The job board appears on each page, but the jobs shown have nothing to do with the page (my usage was similar in concept). Adding a property to each ViewModel would be difficult and time consuming, and a lot of fluff to your tests. I don't think it is worth it in this situation.

I have used a base ViewModel class with the cross cutting data, but if you more than one (e.g., jobs & list of stack exchange sites), you either have to start stuffing extra data in, or some other abuse of a ViewModel, plus you need a ViewModel builder to populate the base data.

As for the magic strings problem, there are a lot of solutions. Constants, extension methods, etc.

With all that said, if you have something that is displayed on your page that depends on the context of the page, a ViewModel is your friend.

Erick

Cryohydrate answered 29/6, 2012 at 18:44 Comment(1)
I know this is old but would it not be better to use use a partial for the job list and @{Html.RenderAction("SomeAction", "SomeController");} from the view?Valerle
M
1
  1. No. Use ViewModels.
  2. No. If you design a perfect ViewModel, you never need a ViewBag.
Mirianmirielle answered 29/6, 2012 at 12:48 Comment(0)
M
1

If you cannot re-design EXISTING ViewModel use ViewBag.

Mastersinger answered 17/10, 2013 at 16:25 Comment(0)
T
1

If there were no use cases for it, it wouldn't be implemented in the first place. Yes you can do everything with ViewModels, but what if you don't really need one? One such scenario is editing entities. You can pass DTO directly as a model.

@model CategoryDto
<div class="md-form form-sm">
    <input asp-for="Name" class="form-control">
    <label asp-for="Name">("Category Name")</label>
</div>

But what if you want to select Category parent? Entity DTO ideally holds only it's own values, so to populate select list you use ViewBag

<select asp-for="ParentId" asp-items="ViewBag.ParentList">
    <option value="">None</option>
</select>

Why do this? Well if you have 50 types of entities each with some sort of select from different values, you just avoided creating 50 extra ViewModels.

Tinworks answered 13/1, 2018 at 0:42 Comment(0)
E
1

I thought I'd give my opinion on this, as I've used the ViewBag extensively.

The only real benefits you'll get from using it are for a small project, or in cases where you have a new project and just want to get the ball rolling and not have to worry about creating loads of model classes.

When your project is more mature, you may find issues with unexpected behaviour caused by using weak typing all over your application. The logic can be confusing, difficult to test and difficult to troubleshoot when things go wrong.

I actually went down the route of completely removing the ViewBag from my applications, and preventing other developers from using it within the same codebase by throwing compilation errors when they try to, even within Razor views.

Here's a sample ASP.NET 5 project on GitHub where I've removed it: https://github.com/davidomid/Mvc5NoViewBag

And here's a blog post where I explain the motivations for removing it and an explanation on how the solution works: https://www.davidomid.com/hate-the-aspnet-mvc-viewbag-as-much-as-i-do-heres-how-to-remove-it

Excellent answered 19/2, 2019 at 17:42 Comment(0)
P
0

2.Are there situations where a ViewBag is absolutely necessary?

In some case you'll need to share your data from the Controller across the layouts, views and partial views. In this case, ViewBag is very helpful and I doubt there's any better way.

Procuration answered 19/10, 2017 at 2:54 Comment(0)
R
0

At the risk of opening up an old can of worms here, let me offer a tiny bit of insight. Regardless of what might be the "best practice," let me offer the real-world experience that the extensive use of ViewBag can be a nightmare source of niggling, hard to find bugs and issues that are an utter nuisance to track down and resolve. Even if an agreeable notion or rule for the use of ViewBag can be established, they too easily become a crutch for junior developers to rely on to distraction AND discourage the development of proper, strongly typed ViewModels.

Unfortunately, too many "tutorial" YouTube videos show the use of ViewBags for a demonstration purposes and offer little to no insight on when such a practice isn't appropriate for production code. Yes, there may be times when use of the ViewBag may be a suitable solution to a given problem, but can lead to a long and winding road of frustration and poor maintainability. At the risk of overcorrecting in the cautious direction, I would encourage younger developers not to rely on the ViewBag until they get more experience with MVC, develop a natural sense of when and how ViewModels are useful, and then after that time develop a more seasoned sense of when the use of the ViewBag is appropriate.

Rouvin answered 13/12, 2021 at 15:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.