If you’re new to ASP.NET MVC, you might be wondering what these two things are and when to use each one. If you’ve been using MVC and are just new to version 3 of MVC, you are probably wondering what this new ViewBag is for and if it’s different from the ViewData you’ve been using. In the beginning of the Summer, I had the opportunity to explain this difference to the two NimblePros interns when they started working on ASP.NET MVC 3 for the first time. This post should serve as a reference for them, me, and anyone else who is interested in knowing more about these two objects.
ViewBag and ViewData serve the same purpose in allowing developers to pass data from controllers to views. When you put objects in either one, those objects become accessible in the view. This is one way we interact between the view and the controller in ASP.NET MVC. We pass data from the view to the controller by placing it in these objects.
How ViewData Works
ViewData is a dictionary of objects that are accessible using strings as keys. This means that we will write code like this:
In the Controller
public ActionResult Index()
{
var softwareDevelopers = new List<string>
{
"Brendan Enrick",
"Kevin Kuebler",
"Todd Ropog"
};
ViewData["softwareDevelopers"] = softwareDevelopers;
return View();
}
In the View
<ul>
@foreach (var developer in (List<string>)ViewData["softwareDevelopers"])
{
<li>
@developer
</li>
}
</ul>
Notice that when we go to use out object on the view that we have to cast it since the ViewData is storing everything as object. Also, we need to be careful since we’re using magic strings to access these values.
How ViewBag Works
ViewBag uses the dynamic feature that was added in to C# 4. It allows an object to dynamically have properties added to it. The code we write using ViewBag will look like this:
In the Controller
public ActionResult Index()
{
var softwareDevelopers = new List<string>
{
"Brendan Enrick",
"Kevin Kuebler",
"Todd Ropog"
};
ViewBag.softwareDevelopers = softwareDevelopers;
return View();
}
In the View
<ul>
@foreach (var developer in ViewBag.softwareDevelopers)
{
<li>
@developer
</li>
}
</ul>
Notice here that we did not have to cast our object when using the ViewBag. This is because the dynamic we used lets us know the type. Keep in mind that these dynamics are as the name suggest, dynamic, which means that you need to be careful as these are basically magic properties instead of magic strings.
ViewBag and ViewData Under the Hood
So these two things seem to work almost exactly the same. What’s the difference? The difference is only in how you access the data. ViewBag is actually just a wrapper around the ViewData object, and its whole purpose is to let you use dynamics to access the data instead of using magic strings. Some people prefer one style over the other. You can pick whichever you like. In fact, because they’re the same data just with two different ways of accessing it, you can use them interchangeably. (I don’t recommend this, but you can do it.) If you want you are able to put data into the ViewBag and access it from the ViewData or put stuff in the ViewData and access it in the ViewBag.
This is all that the ViewBag property is. It’s just a DynamicViewDataDictionary with the ViewData as its data.
public dynamic ViewBag
{
get
{
if (_dynamicViewData == null)
{
_dynamicViewData =
new DynamicViewDataDictionary(() => ViewData);
}
return _dynamicViewData;
}
}
Then when we access the dynamic members of the DynamicViewDataDictionary, we are actually just getting this override of the DynamicObject’s TryGetMember. In this method, it’s just using the name of the member we tried to access as the string key for the ViewData dictionary.
public override bool TryGetMember(
GetMemberBinder binder, out object result)
{
result = ViewData[binder.Name];
return true;
}