Session state is not available in this context - asp.net

I want to read session id in application error event but always get error "Session state is not available in this context". Why? The strange thing is that I have the same code in another asp.net app and everything works fine.
void Application_Error(object sender, EventArgs e)
{
var sessionId = Session.SessionID;
//skipped code
}

The session object may not be available this is dependent on when the error occured.
For example if an error occured on Begin_Request the session would not be available as it has not yet been created.
So in summary sometimes it will work sometimes not, depending on when the error occured.
Best to check the state of the session object before accesssing the session id e.g.
HttpContext context = HttpContext.Current;
if (context != null && context.Session != null) ...

check if any event missing in c# which is mapped to a control or issue in design part

Application_error can fire in situations where a session is not present, for example when the garbage collector cleans up. The source of the error may not have been a user thread.
Just check whether session is null first.
Simon

You may get this error if you are using an Out-of-Process state mode for ASP.NET state server. You need to mark any classes you wish to save to session state with the [Serializable] attribute

Related

ASP.NET MVC Session Variables Lost

My session variables are being lost between pages. Interestingly, this seems to be environment-specific - in our production environment, this works fine, in our test environment, we lose the session variables. This previously used to work in our test environment with the same code, which leads me to believe it's some IIS or server setting that's different.
This is an integration to SFDC where I am adding some session variables on page load. Then, after a user goes through a login flow, SFDC calls back and I try to read those session variables.
Here's how I set the session variables:
Session.Add("tenantID", tenantId);
Session.Add("clientID", tenantInfo.SalesforceKey);
Session.Add("session", session);
Session.Add("clientSecret", tenantInfo.SalesforceSecret);
Session.Add("userEmail", user.Email);
Logger.Debug("Set session tenantID to " + int)Session["tenantID"]).ToString()); // This outputs the proper value.
However, in our callback function in the same controller, when running this code, all session variables are null.
public ViewResult Callback(string code)
{
Logger.Debug("Entering callback, code:" + code);
Logger.Debug("Session vars:");
if (Session["tenantID"] == null) // This is true
Logger.Debug("tenantID: null");
if (Session["clientID"] == null) // This is true
Logger.Debug("clientID: null");
if (Session["session"] == null) // This is true
Logger.Debug("session: null");
if (Session["clientSecret"] == null) // This is true
Logger.Debug("clientSecret: null");
// etc...
}
Initially I thought session was being ended, so I added the following in Global.asax. There's no session ended log line output until well after the callback executes.
void Session_End(Object sender, EventArgs E)
{
// Clean up session resources
Logger.Info("session ended for " + (string)Session["userEmail"]);
}
void Session_Start(Object sender, EventArgs E)
{
// Clean up session resources
Logger.Info("session started.");
}
Some clues that might help here:
- I ran a fiddler to capture the initial page load and the callback, and the ASP.NET session ID was the same in both requests:
(Page Load): Cookie: ASP.NET_SessionId=j1ggxuamkc2rk3q03z2vwye1
(Callback): Cookie: ASP.NET_SessionId=j1ggxuamkc2rk3q03z2vwye1
Previously, our logger statements would output to one file, however, we use log4net, and it now seems to be creating a second file to output the callback logger statements. In production, we only see one file. If I get a session end log from the Global.asax code in the first file (associated with page load), I can read the session values. If I get a session end log in the second log file (associated with callback), the session values are null again.
My web.config does not have any sessionState element included, and this is set the same across production and test.
Thank you for your help.
Here are the IIS Session State settings for that web application:
Session State Mode settings: Set to In Process
Cookie Settings: Mode: Use Cookies
Name: ASP.NET_SessionId
Time-out: 20 minutes
Regenerate expired session ID is unchecked
Use hosting identity for impersonation is checked
Compare the settings for the application pools between the test and prod environment.
I have also similar situation where our application runs fine in server and not in local due to session variable null. If you are implementing sessionfilter in MVC, it is better to run the application in IIS Express in visual studio instead of visual studio development server. That solves our problem of session loss.

Session State Can not be Saved, It was already Flushed by Application

In my Web Application, i am getting an error. "Session state has created session ID. But It can not save it because it was already flushed by application".
I googled for this issue and found that i have to store session id in Global.asax Session_Start Event.
string id = Session.SessionID;
But it was already exist in my application. I am not sure what else is causing issue. I was not using Response.Flush() also.
Can anyone please explain about this issue & fix for it.
That happens because sometimes (depending on the web.config configuration) the SessionID is not set in the cookie when Session_Start event executes in the global asax.
You encounter this error because at somepoint in the pagelifecycle a variable is set in the session. After the request ends, ASP.NET tries to set the SessionID too, but if the Request was flused (eg. this can be done by Response.Write or AJAX itself flushes the response) this exception will be thrown.
A simple fix would be (in the global.asax file):
void Session_Start(object sender, EventArgs e)
{
// Code that runs when a new session is started
//Ensure SessionID in order to prevent the folloing exception
//when the Application Pool Recycles
//[HttpException]: Session state has created a session id, but cannot
// save it because the response was already flushed by
string sessionId = Session.SessionID;
}

ASP.NET session is new for each request unless you write down something

I need unique session id but each it's new unless you write something in it.
The fix looks like this Session["stubkey"] = "fsdufhusd" in page load method.
It's pretty odd to me. Is there any way to init session or probably I do something wrong with configs?
thanks in advance.
The SessionID documentation recommends the same work-around you're using:
When using cookie-based session state,
ASP.NET does not allocate storage for
session data until the Session object
is used. As a result, a new session ID
is generated for each page request
until the session object is accessed.
If your application requires a static
session ID for the entire session, you
can either implement the Session_Start
method in the application's
Global.asax file and store data in the
Session object to fix the session ID,
or you can use code in another part of
your application to explicitly store
data in the Session object.
You don't need to initialize the session on page_load. You can initialize the session on Global.asax like this
protected void Session_Start(Object sender, EventArgs e)
{
Session["init"] = 0;
}

How to detect session timeouts when using cookieless sessions

I'm currently working on a ASP.Net 3.5 project and trying to implement session timeout detection. I know how to do it with enabled session cookies, but without i'm totally lost.
When session timeout occurs i want to redirect the user to some custom page.
Can someone explain me how to do it?
My cookie based solution looks like this and i wan't to reproduce its behaviour:
if (Session.IsNewSession && (Request.Cookies["ASP.NET_SessionId"] != null))
Response.Redirect("...");
Session_End in the global.asax should always be fired, despite the type of session used.
-edit: you might also be interested in
Session.IsNewSession
as this gives you information on new requests whether the previous session could have been timed out.
It looks like i've found a solution. I'm not very happy with it, but for the moment it works.
I've added a hidden field to my page markup
<asp:HiddenField ID="sessionID" runat="server" />
and following code to my CodeBehind
public void Page_Load(object sender, EventArgs eventArgs)
{
if (Context.Session != null) {
if (Context.Session.IsNewSession) {
if (!string.IsNullOrEmpty(sessionID.Value)) {
Response.Redirect("~/Timeout.aspx")
}
}
sessionID.Value = Context.Session.SessionID;
}
}
You also need to add this to your Web.config or ASP ignores all posted form fields
<sessionState cookieless="true" regenerateExpiredSessionId="false"/>
regenerateExpiredSessionId is the important attribute.
It pretty much works the same way - the session service updates a timestamp every time ASP.NET receives a request with that session ID in the URL. When the current time is > n over the timestamp, the session expires.
If you put something in session and check to see if it's there on each request, if it is not, you know the session is fresh (replacing an expired one or a new user).
I'd take a look at the "Database" section of AnthonyWJones' answer to a similar question here:
ASP.Net Session Timeout detection: Is Session.IsNewSession and SessionCookie detection the best way to do this?
In your session start event, you should be able to check a database for the existence of the SessionID - I assume that if I request a page with the SessionID in the URL, then that is the SessionID that I'll use - I've not tested that.
You should make sure you clear this DB down when a user logs out manually to ensure that you store a new instance of your flag.
If you don't like Session_End, you can try a very quick and dirty solution. Set up a Session["Foo"] value in Session_Start in global.asax, then check for Session["Foo"] in your page. If is null, the session is expired..
This is one of the solutions proposed in the Nikhil's Blog. Check it.

accessing SessionState in Global.Application_Error

In the Application_Error method in Global.asax I am trying to retrieve a value from session state.
I am able to access session state as long as I throw the exception. EG:
thow new Exception("Test exception");
However if it is an unhandled exception, i get the following error when trying to access session state: "Session state is not available in this context.".
Why the differences in behavior, is there a work around?
Thanks.
I hate ASP.NET sometimes...
So generating an error using:
Response.Redirect("thispagedoesnotexist.aspx", false);
The above line will redirect to Application_Error with session state not available
However
throw new Exception("test");
The above line will redirect to Application_Error with session state AVAILABLE
So instead of doing this all in Application_Error, in one spot, I will have to use try/catches through out my code to catch errors. Then gather data from session, log and email error details, then finally redirect to friendly error page. Lots of extra code..
Conclusion: Application_Error is worthless.
I think you are trying to access the session through HttpContext.Current.Session. I believe the difference in behavior is that in the unhanded exception handler, the request has gone into "Failsafe" mode and the page lifecycle (including loading and disposing the session) has finished.
Check out this page on the lifecycle for more info

Resources