When to use ViewBag, ViewData, or TempData in ASP.NET MVC 3 applications

Share this post...
facebooktwittergoogle_plusredditlinkedinmailfacebooktwittergoogle_plusredditlinkedinmail

“When should I use a ViewBag vs. ViewData vs. TempData objects?” — a frequent question in online forums, during presentations, and at events. There are enough similarities and differences between these objects that warrant a closer look to see exactly how you can use each of these objects while developing MVC applications.

All three objects are available as properties of both the view and controller. As a rule of thumb, you’ll use the ViewData, ViewBag, and TempData objects for the purposes of transporting small amounts of data from and to specific locations (e.g., controller to view or between views). Both the ViewData and ViewBag objects work well in the following scenarios:

  • Incorporating dropdown lists of lookup data into an entity
  • Components like a shopping cart
  • Widgets like a user profile widget
  • Small amounts of aggregate data

While the TempData object works well in one basic scenario:

  • Passing data between the current and next HTTP requests

If you need to work with larger amounts of data, reporting data, create dashboards, or work with multiple disparate sources of data, you can use the more heavy duty ViewModel object. See my detailed blog post on ViewModels for more details on working with ViewModels.

ViewData & ViewBag objects

  • ViewData
    • ViewData is a dictionary object that you put data into, which then becomes available to the view. ViewData is a derivative of the ViewDataDictionary class, so you can access by the familiar “key/value” syntax.
  • ViewBag
    • The ViewBag object is a wrapper around the ViewData object that allows you to create dynamic properties for the ViewBag.

Both the ViewData and ViewBag objects are great for accessing extra data (i.e., outside the data model), between the controller and view. Since views already expect a specific object as their model, this type of data access to extra data, MVC implements it as a property of both views and controllers, making usage and access to these objects easy. 

The syntax and usage of the ViewBag, ViewData, and TempData objects are outlined in the following code sample, which populates a featured product object that a view renders as in a bakery’s home page:

public class HomeController : Controller

{

    // ViewBag & ViewData sample

    public ActionResult Index()

    {

        var featuredProduct = new Product

        {

            Name = "Special Cupcake Assortment!",

            Description = "Delectable vanilla and chocolate cupcakes",

            CreationDate = DateTime.Today,

            ExpirationDate = DateTime.Today.AddDays(7),

            ImageName = "cupcakes.jpg",

            Price = 5.99M,

            QtyOnHand = 12

        };

    

        ViewData["FeaturedProduct"] = featuredProduct;

        ViewBag.Product = featuredProduct;

        TempData["FeaturedProduct"] = featuredProduct;  

    

        return View();

    }

}

The Index.cshtml view renders the Product object by accessing the code with the same syntax as in the controller. Notice that you’ll have to cast the ViewData and TempData objects, but not the ViewBag.

@using FourthCoffee.Models;

@{    

    ViewBag.Title = "Home Page";

    var viewDataProduct = ViewData["FeaturedProduct"] as Product;

    var tempDataProduct = TempData["FeaturedProduct"] as Product;                

}

<h2>Welcome to Fourth Coffee Bakery</h2>

<div>

    <a href="/Products">

    <img src='@Url.Content("\\Content\\Images\\cake.jpg")' alt="Fourth Coffee Bakery"/>    

    </a>

    <div>

        Today's Featured Product is!

        <br />

        <h4>@ViewBag.FeaturedProduct.Name</h4>

        <h3>@viewDataProduct.Name</h3>

        <h2>@tempDataProduct.Name</h2>

    </div>

    @Html.ActionLink("Test Tempdata","Featured")

</div>

The ViewBag object lets you add dynamic properties to it which makes it a very versatile tool.

Although all three display something when this view renders, but the TempData can be troublesome when used in this manner, and here’s why…

TempData

TempData is meant to be a very short-lived instance, and you should only use it during the current and the subsequent requests only! Since TempData works this way, you need to know for sure what the next request will be, and redirecting to another view is the only time you can guarantee this. Therefore, the only scenario where using TempData will reliably work is when you are redirecting. This is because a redirect kills the current request (and sends HTTP status code 302 Object Moved to the client), then creates a new request on the server to serve the redirected view. Looking back at the previous HomeController code sample means that the TempData object could yield results differently than expected because the next request origin can’t be guaranteed. For example, the next request can originate from a completely different machine and browser instance.

As described below, the syntax for using TempData is the same as ViewData.

// TempData sample

public ActionResult Featured()

{

    var featuredProduct = new Product

    {

        Name = "Assorted Cupcakes",

        Description = "Delectable vanilla and chocolate cupcakes",

        CreationDate = DateTime.Today,

        ExpirationDate = DateTime.Today.AddDays(7),

        ImageName = "cupcakes.jpg",

        Price = 5.99M,

        QtyOnHand = 12

    };

 

    ViewData["FeaturedProduct"] = featuredProduct;

    ViewBag.Product = featuredProduct;

    TempData["FeaturedProduct"] = featuredProduct;

 

    //After the redirect, the ViewBag & ViewData objects are no longer available

    //Only TempData survives a redirect

 

    return new RedirectResult(@"~\Featured\");

}

However, once the controller redirects, the ViewBag and ViewData will contain null values. If you inspect the TempData object with debugging tools after the redirect you’ll see that it is fully populated with a featured product. This is because the redirect is that only, subsequent, request, so only it can access the TempData object without worry.

@using FourthCoffee.Models;

@model FourthCoffee.Models.Product

@{

    ViewBag.Title = "Details";

    var featuredProduct = TempData["FeaturedProduct"] as Product;

}

The customary Session object is the backing store for the TempData object, and it is destroyed more quickly than a regular session, i.e., immediately after the subsequent request. Because of its short lived scope, it’s great for passing error messages to an error page.

Greg shackles has a very comprehensive blog post that covers just about everything you need to know about TempData.

Now that you’ve seen how and when to use ViewData, ViewBag, and TempData objects, you might be wondering what to do when using larger sets of data or more complex scenarios. Fortunately, MVC has ways to deal with these commonly needed scenarios.

Thinking outside the ViewBag

Your requirements might need you to represent the following types of data, which do not fit in well when using ViewBag, ViewData, or TempData objects. The MVC 3 framework contains ViewModel objects for when you need more than ViewData. The type of data that suits ViewModels well is as follows:

  • Master-detail data
  • Larger sets of data
  • Complex relational data
  • Reporting and aggregate data
  • Dashboards
  • Data from disparate sources

You’ll likely run into these or similar scenarios during the app development process.

Summary

The ViewData and ViewBag objects give you ways to access those extra pieces of data that go alongside your model, however for more complex data, you can move up to the ViewModel. TempData, on the other hand, is geared specifically for working with data on HTTP redirects, so remember to be cautious when using TempData.

Share this post...
facebooktwittergoogle_plusredditlinkedinmailfacebooktwittergoogle_plusredditlinkedinmail