views:

196

answers:

5

I'm using TempDate["Message"] to show little update banners as the user does things on my site like this:

[AcceptVerbs(HttpVerbs.Post), Authorize(Roles = "Admins")]
public ActionResult Delete(int id)
{
    _Repo.DeletePage(id); // soft-delete

    TempData["Message"] = "Page deleted!";
    return RedirectToAction("Revisions", "Page", new { id = id });
}

Then in my master page I have this:

<%-- message box (show it only if it contains a message) --%>
<% string Message = (TempData["Message"] ?? ViewData["Message"]) as string; 

   if(!string.IsNullOrEmpty(Message)){
       %>
       <div id="message"><%:Message %></div>
   <% }

   TempData["Message"] = null; ViewData["Message"] = null; %>

I hit both TempData and ViewData because I read somewhere that TempData should be used for redirects and ViewData should be used otherwise.

The issue is: often the message won't show up right away. Sometimes it takes a click or two to different parts of the site for the message to show up. It's very strange.

Any ideas?

A: 

Your app's behavior is the one you'd expect if you're using TempData where you should be using ViewData.

You want to double-check that you're storing your status feedbacks in TempData only when the controller does a re-direct. Otherwise, you should use ViewData.

Larry K
Yes, this is what I'm doing. `TempData` for redirects, `ViewData` otherwise.
Michael Haren
+1  A: 

You should verify all places where you use TempData["Message"] in your code. Corresponds to http://stackoverflow.com/questions/2642062/asp-net-mvc-does-browser-refresh-make-tempdata-useless you can read TempData["Message"] only once (see also http://forums.asp.net/p/1528070/3694325.aspx). During the first uage of TempData["Message"], the TempData["Message"] will be deleted from the internal TempDataDictionary.

Probably it would be better to use TempData["Message"] only inside of Revisions action of the Page controller and not inside of master page or inside a View.

Oleg
I'm familiar with the read-once rule--I think I observe it. Are you saying that tempdata shouldn't be used from views or master pages? Can I get a source for that?
Michael Haren
What I mean to say is that I suppose that you have some effect of read-once rule which can exist for example in a multi-user environment and could be not so easy located. So if you use `TempData["Message"]` before redirecting to `Page/Revisions` action, it seems to me that the reading of `TempData["Message"]` once inside of `Page/Revisions` and saving it somewhere in the model to be able to use in your master page will make you sure that you have full control over the situation and you will have no strange effects. Just try to do this and you will see whether the strange effects still exist.
Oleg
+1  A: 

TempData is not intended to pass data to views, hence the name ViewData for that purpose. In fact, I can't think of a reason to use TempData from within a view definition at all...

One very common usage of TempData is the passing of information between controller actions when you do a redirect (the Revisions action in your example above, for instance, would be able to make use of your TempData["Message"] variable).

This is common practice in the PRG means of coding MVC interactions (Post-Redirect-Get) since you often need to pass information from the initial target action when doing the Redirect to the Get. An example of how this might be useful in a Get is below where I often just default to a new viewmodel UNLESS there is one already passed from a redirect in TempData:

public ActionResult System() {
   SystemAdminVM model = (SystemAdminVM)TempData["screenData"] ?? new SystemAdminVM();

One more thing; I see you explicitly clearing your TempData and ViewData dictionary entries in your view. You don't need to do that as by that point they are at the end of their life spans anyway...

Happy coding!

Tahbaza
Thanks for the help! Is there a standard pattern for doing what I'm trying to achieve here-- sending messages to the master page view from many different controller actions?
Michael Haren
A: 

This smells like you need a couple of unit tests to confirm the behavior you're seeing. Try writing up a couple using this example as a starting point:

http://weblogs.asp.net/leftslipper/archive/2008/04/13/mvc-unit-testing-controller-actions-that-use-tempdata.aspx

AndrewDotHay
A: 

If you have configured multiple worker process for your application, but session state mode is "InProc", then you can't use default TempData implementation, as session state becomes unusable. (see ASP.NET session state and multiple worker processes)

You could try to use MvcFutures CookieTempDataProvider instead.

I don't think I'm doing the web-garden thing (I'll double check), thanks!
Michael Haren