views:

94

answers:

2

I have a div in my master page that is only displayed if Session["message"] contains data:

<%
    if (!String.IsNullOrEmpty(Session["message"].ToString()))
    {
%>        
        <div id="sessionMessage" class="sessionMessage"><%:Session["message"].ToString()%></div>
<%
    }
%>  

I use it to pass general info to users for both action success and failure.

I tested it on failures, and it works great. Just set the Session["message"] in the catch block and return a new instance of the view:

{ 
   //Invalid - redisplay with errors
   Session.Add("message", "That object already exists.  Please try again.");
   return View(new DetailViewModel());            
}

Problem: However, for the success cases, which involve a RedirectToAction, the Session["message"] always gets cleared out by the time I get to the Master Page:

//Send message to view for user to see
Session.Add("message", "Object added.");

//Redirect to the details
return RedirectToAction("Details", new { id = viewModel.MyObject.ObjectId });

I considered switching to TempData, but it throws a nullreference error on initial page load. I assume this is because TempData is a member of the Controller class, and the Master Page has no controller per se?

+1  A: 

It's just fine to use TempData in a master page. But if the TempData["message"] doesn't happen to contain anything, then calling .ToString() on it will give you a null reference exception. Session and TempData behave identically in this respect. This principle difference is that TempData is cleared when you read it, and Session is not. So you're more likely to see the problem with TempData, but your code has the same potential bug with either one.

Craig Stuntz
See String.IsNullOrEmpty()
David Lively
@David, if you do `if (String.IsNullOrEmpty(TempData["message"])) { //...` in MVC 2 then you just cleared `TempData["message"]`. Reading it clears it in MVC 2.
Craig Stuntz
I'm using String.IsNullOrEmpty(). What are you referring to?
morganpdx
Ah so if the key "message" doesn't exist it throws the null reference...got it. But that still doesn't answer why the session is getting cleared out every time I call RedirectToAction.
morganpdx
`Session` *shouldn't* be cleared when you redirect. But that is expected behavior if session cookies are blocked or broken -- the user gets a new session key with each request in that case. ...or perhaps the `Session["message"] = ""` code you refer to elsewhere is running when you don't expect it to?
Craig Stuntz
It only gets called if there's a value in that session variable, and only after it's displayed - I tested that it works as expected for error conditions. Since TempData is stored in the session, won't I have the same issue? I.e., moving to TempData will not solve the problem I'm having...?
morganpdx
@Craig wow: I honestly hadn't run into that. Thanks for the insight!
David Lively
@Craig: Check this out: http://weblogs.asp.net/bleroy/archive/2004/08/03/Don_2700_t-redirect-after-setting-a-Session-variable-_2800_or-do-it-right_2900_.aspx
morganpdx
That's really, really out of date. If that actually helps, then something else is going on. Archaic server?
Craig Stuntz
Yeah, I saw that. Considering where I work, that would be a definite possibility, however. ;/
morganpdx
A: 

I'd strongly encourage you to use TempData for all user alert and notification functionality.

Session can stick around forever while TempData clears after its read or if your using MVC 1 after the next page loads. Using Session means you could give the user a confusing error message that you forgot to clear.

jfar
@jfar - yeah, I didn't include the Session["message"] = ""; line that is in my code. I'm already clearing it out as soon as I use it...which kind of leads me to think I should be using TempData anyway!
morganpdx
I finally figured out how to access TempData in my helper method, which was the sticking point for me moving from Session to TempData: HtmlHelper.ViewContext.TempData[""]. Also, for the record, it seems the reason the Session key I was setting was not persisting was due to the redirect: http://weblogs.asp.net/bleroy/archive/2004/08/03/Don_2700_t-redirect-after-setting-a-Session-variable-_2800_or-do-it-right_2900_.aspx
morganpdx