ASP.NET MVC - Session is null

2019-01-08 01:30发布

问题:

I have an MVC3 application on .net4 that its session working in the dev Environment, but not in the production.
In the production I logged the sessionID and the it is the same in the moment I Set and Get from the session.

When I try to get the session I am getting Null Exception.

This is how I access the session:

public static class HandlersHttpStorage
{
    public static string TestSession
    {
        get
        {
            return HttpContext.Current.Session["time"];//This is null
        }
        set
        {
            HttpContext.Current.Session.Add("time", value);//DateTime.Now.ToString()
        }
    }
}

What's makes me worried is that the behavior in the production is different than the development, even though the web.config is the same.

回答1:

Solution 1:

Link: HttpContext.Current.Session is null when routing requests

Got it. Quite stupid, actually. It worked after I removed & added the SessionStateModule like so:

<configuration>
  ...
  <system.webServer>
    ...
    <modules>
      <remove name="Session" />
      <add name="Session" type="System.Web.SessionState.SessionStateModule"/>
      ...
    </modules>
  </system.webServer>
</configuration>

Simply adding it won't work since "Session" should have already been defined in the machine.config.

Now, I wonder if that is the usual thing to do. It surely doesn't seem so since it seems so crude...

Solution 2:

Link: HttpContext.Current.Session null item

sessionKey may be changing, you probably only need to do:

HttpContext.Current.Session["CurrentUser"]

Or the session may be expiring, check the timeout:

http://msdn.microsoft.com/en-us/library/h6bb9cz9(VS.71).aspx

Or you may be setting the session value from somewhere else, normally i control access to Session/Context object through one property

static readonly string SESSION_CurrentUser = "CurrentUser";

public static SiteUser Create() {     
 SiteUser.Current = new SiteUser();      
 return SiteUser.Current;
}

public static SiteUser Current {     
 get {         
  if (HttpContext.Current.Session == null || HttpContext.Current.Session[SESSION_CurrentUser] == null) {             
   throw new SiteUserAutorizationExeption();         
  }          
  return HttpContext.Current.Session[SESSION_CurrentUser] as SiteUser;     
 } 
 set {
  if (!HttpContext.Current.Session == null) {
   HttpContext.Current.Session[SESSION_CurrentUser] = value;
  }
 }
} 


回答2:

Another possible cause/solution is that IE doesn't save cookies if the domain name has an underscore (because strictly speaking domain names can't have underscores, so you'll probably only encounter this in development), e.g. http://my_dev_server/DoesntWork. Chrome or Firefox should work in this scenario, and if you change the domain name you're using to not have an underscore problem solved.

Ref:

  • http://blog.smartbear.com/software-quality/internet-explorer-eats-cookies-with-underscores-in-the-hostname/
  • http://social.msdn.microsoft.com/Forums/ie/en-US/8e876e9e-b223-4f84-a5d1-1eda2c2bbdf4/ie7-cookie-issue-when-domain-name-has-underscore-character-in-it?forum=iewebdevelopment


回答3:

For me, I found that HttpContext.Current was null, so I created it:

System.Web.HttpContext c = System.Web.HttpContext.Current; 

And I passed that into my function that was in my other class, like this:

string myString = "Something to save";
SessionExtensions.SetDataToSession<string>(c, "MyKey1", myString);

I had actually wanted my function to be a real extension method off of Session like the one below, but what I found was this HttpSessionStateBase session was null, it would give the NullReferenceException when I tried to add anything to Session using it. So this:

public static class SessionExtensions 
{ 
   /// <summary> 
   /// Get value. 
   /// </summary> 
   /// <typeparam name="T"></typeparam> 
   /// <param name="session"></param> 
   /// <param name="key"></param> 
   /// <returns></returns> 
   public static T GetDataFromSession<T>(this HttpSessionStateBase session, string key) 
   { 
       return (T)session[key]; 
   } 
   /// <summary> 
   /// Set value. 
   /// </summary> 
   /// <typeparam name="T"></typeparam> 
   /// <param name="session"></param> 
   /// <param name="key"></param> 
   /// <param name="value"></param> 
   public static void SetDataToSession<T>(this HttpSessionStateBase session, string key, object value) 
   { 
       session[key] = value; 
   } 
} 

That Microsoft had here: https://code.msdn.microsoft.com/How-to-create-and-access-447ada98 became this, instead:

public static class SessionExtensions 
{ 
   /// <summary> 
   /// Get value. 
   /// </summary> 
   /// <typeparam name="T"></typeparam> 
   /// <param name="session"></param> 
   /// <param name="key"></param> 
   /// <returns></returns> 
   public static T GetDataFromSession<T>(HttpContext context, string key) 
   { 
        if (context != null && context.Session != null)
        {
            context.Session.Abandon();
        }

        return (T)context.Session[key];
   } 
   /// <summary> 
   /// Set value. 
   /// </summary> 
   /// <typeparam name="T"></typeparam> 
   /// <param name="session"></param> 
   /// <param name="key"></param> 
   /// <param name="value"></param> 
   public static void SetDataToSession<T>(HttpContext context, string key, object value) 
   { 
       context.Session[key] = value; 
   } 
} 

And I was able to retrieve my data like this:

System.Web.HttpContext c = System.Web.HttpContext.Current;
string myString = SessionExtensions.GetDataFromSession<string>(c, "MyKey1");

And, of course, since HttpContext.Current and Session now exists, I was able to even simplify that to be:

 string myString = Session["MyKey1"].ToString();

If this had been object, you would put the object's type in place of <string> in the SetDataToSession() function:

List<string> myStringList = new List<string>();
myStringList.Add("Something to save");
SessionExtensions.SetDataToSession<List<string>>(c, "MyKey1", myStringList);

And to retrieve it:

System.Web.HttpContext c = System.Web.HttpContext.Current;
List<string> myStringList = SessionExtensions.GetDataFromSession<List<string>>(c, "MyKey1");

or simply:

List<string> myStringList = (List<string>)Session["MyKey1"];