Microsoft has made a change to the behavior of TempData that we need to be aware of in MVC 2 and 3. TempData now no longer completely clears at the end of a controller action cycle. TempData can now (automatically and without you changing anything) persist through to other pages. 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. These changes could potentially be very bad where we have coded under the old assumption.

Here’s the details:

Any code that sets a value to TempData but doesn’t read it will leave that value in TempData until some page or controller action happens to read a key with the same name or until the user closes the browser. After upgrading a project from MVC 1, I ran into one scenario where a page throwing a user input error on one page caused a completely different page to throw a system error. It started with a page throwing a user input error. Because of a bug in my code that threw a null object exception, the user was redirected to the system error page. But since the original user input TempData key was never read (and therefore never cleared from TempData), weird behavior occurs when I leave the system error page and go to another page. The other page now detects the original user input error in TempData and tries to cast the original view model to its page’s view model, which throws an Invalid Cast exception, and sends the user to the system error page. I can easily solve this situation by fixing my null object bug, but there isn’t an obvious solution to the now-persistent TempData issue. So we all need to be aware that we may see some weird bugs in the future with causes that are not readily apparent due to the new wormhole behavior of TempData.

At one point I was toying with the idea of putting ModelState into ViewData to use with validation (this is how MvcContrib does it), good thing I didn’t:

I couldn’t find any mention of the change in any of the release notes for MVC 2 (beta, RC, or RTM) from Microsoft, ScottGu, or Phil Haack. I believe this is the extent of the Microsoft “announcement”…in Jacques Eloff’s blog (a self-described “Code Monkey” working at Microsoft), titled “TempData Improvements”:

In the end we opted for something simpler [than Ruby On Rails] that addressed the scenarios we wanted to solve while limiting the number of changes to the existing API. The outcome of the changes we made resulted in the following rules that govern how TempData operates:

1. Items are only removed from TempData at the end of a request if they have been tagged for removal.
2. Items are only tagged for removal when they are read.
3. Items may be untagged by calling TempData.Keep(key).
4. RedirectResult and RedirectToRouteResult always calls TempData.Keep().

« »