I'm working on an application using ASP.NET 4.0 and MVC 2.0. If it's in any way relevant, I'm using VS2010.
I'm running into complications with TempData. I did not write the original code, but it isn't working correctly and I'm attempting to fix it. I don't have a lot of experience working with TempData and ViewData.
I have an Index action as follows (pseudocode):
public virtual ActionResult Index()
{
var vm = new IndexViewModel();
// some code here to set up the ViewModel
if (TempData.ContainsKey("Success"))
vm.Success = true;
return View(MVC.Controller.Views.Index, vm);
}
And I have a POST action as follows (pseudocode):
[HttpPost]
public virtual ActionResult Index(IndexViewModel vm, List<int> formData)
{
if (DoSomethingWithData(formData))
{
TempData["Success"] = true;
return RedirectToAction(MVC.Controller.ActionNames.Index);
}
TempData["Message"] = "Failed to use formData";
return View(MVC.Controller.Views.Index, vm);
}
The view emits a form and prefaces it with a success message if vm.Success is true. It will also emit the message in TempData["Message"] if it is present.
The first time I come to the page I get just the form. I enter INVALID form data and submit it... and I get the form prefaced by the error message as expected. (I know there's poor design here since it doesn't redirect... and you get poor user experience with refresh, etc. but I'm not worried about that yet) This is all great.
The problem manifests when I use VALID form data. If I submit valid form data, I get the page back prefaced with a success message as expected, but if I refresh the page the success message is still there. Indeed if I go to a completely different part of the site and navigate back, the success message is still there. For some reason after a redirect and read, the tempdata is still there. There has been both a redirect and a read... shouldn't the temp data now be clear?
I'm reasonably certain that the other places I navigate to aren't setting TempData["Success"] for any reason, but to be sure I've navigated to things like Google, and come back directly to the URL for this page, and it still seems as though TempData["Success"] is populated.
It's very clear that either I don't clearly understand how TempData is supposed to function (unsurprising) or something unusual is happening that I simply don't have the experience to see.
Any advice is welcome!
Thanks, Dave
[EDIT]
The view doesn't actually emit the form when there's a success message... it only emits the success message.
The view looks more or less like this:
<% if (TempData.ContainsKey("Message")) { %>
Emit message...
<% } %>
<% using (Html.BeginForm(MVC.Controller.ActionNames.Index,
MVC.Controller.Name,
FormMethod.Post,
new { id = "form"})) { %>
<% if (!Model.Success) { %>
Emit form...
<% } else { %>
Emit confirmation message...
<% } %>
<% } %>
Francisco pointed me towards something I hadn't considered... but it turns out the constructor for the viewmodel sets Success to false... so it's not something odd with that. I know for sure that TempData["Success"] is still set (rather than something like foolishly reusing a viewmodel with success set to true) because I've stepped through the code and it continually steps into that if statement where it sets vm.success = true, even after a refresh.
Just adding this as I said in my comment. I suggest to do
Instead of
... so it counts as a TempData read. Glad it worked. Regards
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.
Here are more details: warning-mvc-nets-tempdata-now-persists-across-screens