ASP.NET MVC TempData Is Really RedirectData

Posted by on in Blogs
Update: This post was written for MVC 1. TempData behaves completely differently in MVC 2 Beta and higher. In these versions, TempData is cleared only when it is read (or when the session expires).

Many people seem to be confused about the TempData feature in ASP.NET MVC. TempData behaves like the ViewData dictionary, except that it persists until the next request from the same browser.

Because of this, TempData should only be used when you know exactly what the next request is going to be. If you set TempData and your action then returns a ViewResult, then the next request, whatever it happens to be (an AJAX request, another page the user opened in a different tab, etc.), is going to see the TempData value you set, and no other request will see it. I'm guessing that this is never the behavior you want.

Realistically, this means that you should only use TempData immediately before you redirect (in other words, immediately before you return a RedirectResult), because this is the only time when you are sure what the next request from that browser is going to be. I actually think that RedirectData would be a better name for this property. Someone, perhaps Steve McConnell, once noted that you should never include "temp" in a variable name, since variables are, by definition, temporary. "Temp data," to me, is synonymous with "variable." The (functionally similar) "flash" feature in Rails is even more badly named.

If your controller action returns a ViewResult, and you are tempted to put data into TempData, don't. Use ViewData, instead, in this case.

This may lead to a situation where you might need to have a view look into both ViewData and TempData for a key. One example would be if you have an area in your Site.Master to display error messages on the page. It is likely that one controller action will need to send a message to the view via ViewData (because that action returns a ViewResult), while another action will need to send a message to the view via TempData (because that action returns a RedirectResult, as part of a POST/redirect/GET cycle). In this case, you can use code like this in the Site.Master:

<%= ViewData["Message"] ?? TempData["Message"] %>

Under the hood, TempData works by using server-side Session state, so a distributed session cache like Velocity can be used if your application runs on a server farm. Since the lifetime of data put into TempData is limited to the next request, it is fairly easy to use without worrying about growing the session very large, especially since the most common use for TempData is to store a short error string. But the usual rules on what you can put into a Session apply. If you set the Session state mode to out of process, then the data you put in it must be serializable.


  • Guest
    George Sunday, 1 February 2009

    Craig, I'd rather disagree that "close to impossible" is an acceptable way of dealing with reliability issues. This WILL happen sooner or later.

    Here is the detailed analysis of the race condition:

  • Guest
    Josh Comley Sunday, 5 April 2009

    You could use the routeValues:

    RedirectToAction("MyAction", new MyValues() { ErrorType = 1, Test = true });

    This will put the values in the URL. For small amounts of data, this solves the problem without a race condition.

    If you're really, really concerned about the race condition and want to store more data, or don't want sensitive server-side only data passed via URL, you could do something like this:

    Guid guid = Guid.NewGuid();
    Session[guid.ToString()] = myData;
    RedirectToAction("MyAction", new MyValues() { g=guid.ToString() });

    And then in your view, check the session for a value named with the Guid passed as the "g" parameter in the URL.

    As soon as the view starts rendering you could grab the session data, pull it into the view and clear out the session.

    If it cannot find that guid then they have either visited the same guid URL twice, or their session has expired.

    Like Craig points out, the latter shouldn't be a problem because if you only use this technique on redirects then your session is not going to timeout.

    If the guid is not found, fall back to the default implementation of the view.

    However, if you find yourself ever needing to use this situation then you're probably doing something more deep rooted wrong. Have a think about your whole process - this should be a last resort tool in an obscure situation. Most problems can be resolved in a much purer fashion!

    I haven't considered side issues like session data maximum size, but then temp data maximum size was never discussed, and to be honest I don't know the details!

    Awaiting Hole Picking :)

  • Guest
    Tuan Jinn Nguyen Wednesday, 21 April 2010

    Thank you, I've been looking for this. I need to retain certain amount of data and keep the url clean.

    For example, adding products from a search page to a basket where input data can be invalid, or out of stock or whatever. Those which r valid need to be processed and those which r not will be warned. This is a solution.

  • Guest

    [...] it to pass data to an action when we redirect (Craig Stuntz goes so far as to call TempData “RedirectData” for this very reason). If you’re using TempData for any other purpose than passing [...]

  • Guest
    Arnis L. Thursday, 12 August 2010

    Glad I found this. Found myself losing notice after window.location=blabla.

    Turns out I've forgot to upgrade Mvc framework.

  • Guest

    [...] requirement is actually quite easy to implement using ASP.NET MVC’s TempData container.  Craig Stuntz has a good post on this poorly-named container.  In a nutshell, it’s a session-baked store that persists its [...]

  • Guest

    [...] can use TempData to store your model (this also will be GET request, but model will not be passed in route values [...]

  • Please login first in order for you to submit comments
  • Page :
  • 1

Check out more tips and tricks in this development video: