14 Days Free Technical Video Training from WintellectNOW

  

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

Tags: ASP.NET MVC, ASP.NET, Razor

"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.

58 Comments

  • Rob Conery said

    Hi Rachel - nice post :). I think there's a lot of confusion about this and it's nice to see you tackle it :).

    If I may - it might be worth pointing out that *everything* (aside from TempData) gets popped on ViewData, which in turn is popped onto ViewContext - the only question is "how much misdirection do you want".

    I think what you're alluding to (correct me if I'm wrong) is handling more complex data structures with a typed class rather than pushing simple key-value bits using ViewData - which is a good approach.

    However it's also not exclusive. You can use a ViewModel *with* ViewBag and ViewData:

    ViewBag.MyViewModel = new MyViewModel();

    Since ViewBag is a wrapper for ViewData (as you mention) - it all cycles down to ViewData as a transport mechanism which is used no matter what you do.

    Some people actually prefer this loose association between Controller/View :). For me - I tend to use Dynamic with everything so it doesn't matter :).

    Thanks again for writing this post :).

  • Rachel said

    Great points, Rob! Definitely, they can be used together. And yes, that is my approach - ViewBag for more complex, and the others for the simpler things.

  • Rob Conery said

    Not sure I understand... others? It's all ViewData - are you saying "use a Typed View with a ViewModel when your data is complex"?

    Sorry to push on this - it can be really confusing to people as there are two separate issues here... and no matter what you're using ViewData :).

  • Rachel said

    Oops!! (sometimes the fingers just type what they want!)

    I meant: ViewModel, strongly typed, for more complex scenarios.

    The ViewData/ViewBag/TempData for more simple secnarios.

    Of course, all in general, as every situation is different and there are always exceptions.

  • Tiendq said

    "The MVC 3 framework contains ViewModel objects for when you need more than ViewData."

    I don't think ViewModel is something new in ASP.NET MVC 3. I think you'd better to keep this post for differences between ViewData, ViewBag and TempData, because using ViewModel or not and when is another big topic.

  • itmeze said

    I see Rob Conery point of view...

    Beside that, I do admit that having ViewModel, ViewData and ViewBag is a little bit misleading - especially for beginners. This can be somehow unified (as a matter of fact it all ends as a ViewData). Is it kept like that just because of backward compatibility?

    TempData is of course a completely different story...

    Go for dynamics! :)

  • Jon said

    Just one question, can TempData also be used in scenarios where you need a value to be propagated down to partial views that are rendered through RenderAction in the controller? I had a scenario where the value passed into the URL for a controller action was needed by the partial views too and TempData seemed to be the only way to achieve it.

  • Amr ElGarhy said

    Nice article, I have a question: the tempData get killed after the subsequent request ends, when exactly the ViewData, ViewBag and ViewModel ends?

  • Rachel said

    Tiendq-

    Didn't mean to sound as if I were excluding other verions by using MVC 3 in the sentence as the ViewModel is available in V2 as well.

    And yes, agreed, ViewModels are worth their own post, so I have one here just for them :

    http://rachelappel.com/use-viewmodels-to-manage-data-amp-organize-code-in-asp.net-mvc-applications

  • Rachel said

    itmeze,

    Yes, they can be confusing at times for beginners and some of the features are kept for backwards compatibility.

    LOL dynamics!

  • Rachel said

    Amr,

    ViewData/Bag live until the end of the current request, which is all you need to get data from the model through the controller and to to view.

  • Amr ElGarhy said

    @Rachel
    So this means that TempData has a longer live time, correct?

    Also, what are objects in asp.net have the same behavior as ViewData and TempData?

  • Rachel Appel said

    Amr,

    Yes, however TempData is restricted to the current and subsequent requests only. So, not much longer. It's really only useful, IMO, with the scenario I described above (redirection).

    For ASP.NET Web Forms (I think that's what you're referring to when you say ASP.NET) - you can use the HttpContext.Current.Items collection.

  • Kristofer Hoch said

    Racheal,

    You don't know me, and I only found you because of Rob's blog post about this article.

    I have to say this is a great post. It was a bit confusing, but your dialog with Rob cleared it up.

    I've subscribed to your news letter.

    Sincerely,
    Kristofer Hoch

  • Henrik Stenbæk said

    I’m not sure if I’m reading this correct:

    ”… 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.”

    Since TempData, by default, is saved in session and session is based on the session cookie on the client computer the only request that can get access to ”my” TempData is a request comming from the same machine made with a browser that is sending my session cookie…

  • Rachel said

    Henrik,

    That is correct about how TempData is stored, but the usage/behavior a bit different that a plain session variables, so it's only available to the next request, and then the only way to guarantee access to it properly is to use it on redirects.

  • Henrik Stenbæk said

    Rachel,

    We are talking about MVC 3, right? As i understand it is correct that in MVC 2 TempData is cleared after the next request. But the behavior of TempData change in MVC 3: TempData keys are now only cleared if they’ve been read. Furthermore, if you use RedirectResult or RedirectToRouteResult, they will persist even if they are read.

  • Rachel said

    Henrik,

    Thanks for mentioning that. To be sure, I double checked with Steve Sanderson (ASP.NET team member), and yes you are correct in how it works. I also missed that little tidbit myself!

    His response:

    "It sounds about right, though if I remember correctly, that change was made in MVC v2, not in MVC v3.

    TempData values are marked for deletion when you read them. At the end of the request, any marked values are deleted. The benefit is that if you have a chain of multiple redirections it won’t cause TempData to be emptied like it would in MVC v1 – the values will still be there until you actually use them, then they clear up after themselves automatically."

  • Luke Baughan said

    Brilliant post, extremely comprehensive - it's really cleared my thoughts on passing data outside the model to the view! Now... off to read your post on ViewModels ;o) Thank you!

  • Mike Johnson said

    Can you explain how ViewData and or ViewBag would work in a multi-host environment such as a web farm or Windows Azure ? Wouldn't you be better to push to goold old Session ?

  • Bil Simser said

    Predator

    I don't think Predator knows much about grammar either.

    And the women I know, including Rachel, know more about programming than most seasoned veterans.

  • Dane Morgridge said

    @Predator clearly you must have thought that viewbag was a euphemism for d-bag and thought "Hey that's me!". Then you realized it was about code (which I'm sure you are pretty clueless about) and decided to leave a dumb ass comment to make yourself feel better about yourself. Good job, you succeeded in showing the world how stupid you are.

  • nick said

    very wise information.

    how would one handle the situation where you have an error in your controller that posts you to an error page? Does your temp data disappear because of the exception?

  • Rachel said

    nick,

    It will disappear after it's read on the error page. You can access with the TempData[""] syntax.

    Also - one of the earlier comments by Henrik. He shows some techniques to work w/tempdata

  • Rachel said

    Mike J,

    They'll work the same, if it's Azure. Azure will do all the magic load balancing & related activity so you don't need to worry about the View* objects floating around aimlessly.

    Session should also work the same way as it currently does (not multi-tenant) as well. The downside of using a session variable here would be the extra memory (yes, still a concern with scalability) that it takes to store each one for the default amount of time.

    Hope that helps.
    Rach

  • Mike Johnson said

    Thanks Rachel. It seems tempdata is implemented through session and needs to have the same persistance management mechanism as session does in a webfarm. Just Trying to lean. Its kind of a shame that azure doesnt manage this for you unless you want to roll your own alternative.

  • sean said

    can TempData also be used in scenarios where you need a value to be propagated down to partial views that are rendered through RenderAction in the controller?

  • Rachel said

    Sean,

    That would work technically, as the partial view is part of the processing pipeline of its containing view. That's a bit of an unconventional use though, and the maintenance devs might be a bit confused as to what the code's actually doing (maybe expecting a common error, since TempData is recommended for that). If possible, stick with ViewBag/Data, I think it will serve you better.

  • Bo said

    Hello from Arizona! Great article and very informative as I'm new to all of this so it definitely helps. Might I suggest to maybe update the article with some of the more useful bits of info made in the comments i.e. lifespan and clearing of values with TempData. Would hate to think I would've missed out on that if I hadn't read thru the comments. Will definitely be subscribing to your blog, its a big help!

  • Daniel Lang said

    Hi Rachel,

    Great article, but as it is already said in the comments above the paragraph about TempData is actually wrong. Since MVC2 it has a much longer lifecycle and will only be deleted after it was read or if the session expired.

    Therefore you can safely store quite complex objects within TempData and have them persisted beyond multiple requests during a user (!) transaction. This enables completely new usages of TempData, however, you certainly need to be aware that sessions might expire.

  • Sameer said

    Hi Rachel,
    tnx alot for such great post..im new to mvc3 ..im creating a shopping cart application.i used session to store cart coz its very handy, Now what i want to know is that my instructor told me to use temp data or viewbag/data insted of session..i ve have products controller and cart controller(calls each other for operations)..so pls tell me wats the best approach??
    tnx in advance.

  • Rachel said

    Sameer,

    Go with the ViewBag/ViewData approach, or use Sessions. Sessions are not bad if used sparingly, just don't go dumping all sorts of stuff in them.

  • Rachel said

    dnn,

    Go with the TempData and pass the error message there. If you're looking for a global error handler instead, you can use an ActionFilter to do that, or web.config settings.

  • GotiBandhu said

    Hi,
    this is great stuff, thanks for sharing with us. It's help me lot and this link http://www.mindstick.com/Articles/13768801-20cf-4ff4-b3fa-f7007917b027/?ViewBag%20in%20ASP.NET%20MVC

    also helped me in completing my project.

    Thanks !!!

  • Dpak said

    Rachel,

    Great article!

    One question, does Viewbag/Viewdata also use the Customary Session as the backing store?

  • Rachel said

    Dpak,

    No it doesn't, but you can use the Session object in MVC if you're looking for that.

  • Naren Gokal said

    Hi Rachel,

    Excellent post!!

    Im trying to pass model data from 1 view to another view, and once i get to the other view, i want to post this data to the database

    TEMPDATA, expires at the HTTPGET of the second VIEW i go to, because as you said above, it lasts for 1 session only. If i need the data to be carried forward for more than 1 session, is my only option to use session variables ? I dont think VIEWBAG will work either.

    thanks kindly
    naren

  • Rachel said

    Naren,

    Your model is rendered in view #1, and upon submitting the form there, it sends the data via HTTP POST to some other controller (let's say a controller for view #2). In that controller's action method you can just return the view to view #2. This is the natural way to implement MVC on ASP.NET.

    You could also use a ViewBag, that will work but allowing MVC to do the conventional passing of data should do just fine here.

  • Saeed Neamati said

    Based on what you said here, can we assume that setting an Error in TempData would result in the strange behavior of seeing the error of one page in another page? In other words, is it possible to set an error in TempData, and then without redirect, user see the error in another page?

  • Rachel said

    Saeed,

    Yes, setting the TempData on the current request will allow access to the data in it during the subsequent request, but that is all. After that TempData is wiped clean.

Comments have been disabled for this content.