ASP.NET sessionID will not update - c#

I click on refresh button which should restart session:
protected void btnRefresh_Click(object sender, EventArgs e)
{
HttpContext.Current.Session.Abandon();
HttpCookie mycookie = new HttpCookie("ASP.NET_SessionId");
mycookie.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(mycookie);
LblSessionID.Text = HttpContext.Current.Session.SessionID+
" test btnRefresh_Click";
LblIsNewSession.Text = Session.IsNewSession.ToString();
}
But when the button is clicked, the SessionID value in LblSessionID still displays the old value but another label LblIsNewSession will show it as true for IsNewSession. The LblSessionID will then reflect the actual SessionID value when I use asp.net control (like dropdown) that has autopostback="true" and from there SessionID sticks around.
I do use global.asax
Any idea why LblSessionID isn't behaving as it should and is waiting for next postback to start reflecting actual value?
When I launch the web application, the problem is the same - LblSessionID show different value and then change after first postback and stays the same from there.

That's the way it works - If you Abandon the session it won't reflect that until the next Request. It makes sense if you think about it...
Say you have a user that accesses your site and gets a Session ID of 123 (not reflective of an actual value, I know). When you click your button to get a new Session ID, the user's request is from the old Session, and that is the value that is reflected during that Request. Once the session is reset (or abandoned or whatever), the user gets a new Session ID of 321 and subsequent Request's will then reflect that new session ID.

SessionId is not reliable unless you actually store something (anything) in the session.

try
Session.RemoveAll();
Session.Clear();

It is not your code, it is a documented behavior:
"The Abandon method sets a flag in the session state object that indicates that the session state should be abandoned. The flag is examined at the end of the page request. Therefore, the user can still use session objects after you call the Abandon method. As soon as the page processing is completed, the session is removed."
(source: http://support.microsoft.com/kb/899918)
The Abandon() method flags the session collection for clearing at the end of the request, it does not actually clear it immediately.
You can either call the RemoveAll() or Clear() methods for instant deletion of the objects, or issue a Response.Redirect call to the page itself and re-test for the existence of the data.

Related

SessionID changing at every page call

I'm accessing the SessionID using this code in my class:
HttpContext.Current.Session.SessionID;
however I find that SessionID changes at every page postback, this happens in a short time, so the current session should not expire already. I supposed that the SessionID to remain the same for the whole time until expired.
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.
like
protected void Session_Start(Object sender, EventArgs e)
{
Session["init"] = 0;
}
You should Use the Session_Start method in the application Global.asax file. Below Link may help you
ASP.NET: Session.SessionID changes between requests

Redirect from Global.asax

HttpContext.Current.Response.Redirect("~/default.aspx");
When i use this code in session_end in global.asax
error to me:
Object reference not set to an instance of an object.
why?!
Session_end is not an event that gets called by the user of your application, it's something that gets called by the server when a session times out. So when you try to access HttpContext, it is null because there is no HttpContext to access (no user who is currently performing some kind of interaction with your site).
Your attempt to redirect a non-existing HttpContext will always fail no matter what you do.
When the event SessionEnd is raised the Request and then the Response are null.
HttpContext.Current.Response //this is null
This is by design: Session ends not during a request but when the session timeout
It usually (default config) happens 20 minutes after the last request.
Since there is no request there is also no response.
You need to understand better how Asp.net Session State works
Anyway if you want to redirect the user to a page if the Session is expired you can check for one of your variables stored on session:
protected void Page_Load(object sender, EventArgs e)
{
if (Session["YOUR_VAR_NAME"]==null)
{
Response.Redirect("~/default.aspx");
}
}
Session_End is fired internally by the server, based on an internal timer. Thus, there is no HttpRequest associted when that happens. That is why Response.Redirect or Server.Transferdoes not make sense and will not work.
I hope the above information will be helpful

Using Cache ASP.NET

How can I use Cache in ASP.NET which is accessible by all users not just a specific user context while having a specific key of this cache removed automatically when a user closes the browser window or expires (like a session object) ?
Cache is accessible to all users, you can set it to expire after a period of time:
Cache.Insert("key", myTimeSensitiveData, null,
DateTime.Now.AddMinutes(1), TimeSpan.Zero);
You may remove the cache entry whenever a session expires by implementing the global.asax's session end event
void Session_End(Object sender, EventArgs E)
{
Cache.Remove("MyData1");
}
See this for more details on Cache
Edited:
Regarding your question on how to react when the user closes its browser, I think that this is not straightforward. You could try javascript on the client side to handle the "unload" event but this is not reliable since the browser/client may just crash. In my opinion the "heartbeat" approach would work but it requires additional effort. See this question for more info.
You'll have to use the Session_OnEnd() event to remove the item from the cache. However, this event will not fire if the user just closes the browser. The event will only fire on the session timeout. You should probably add a check to see if the item has already been removed:
public void Session_OnEnd()
{
// You need some identifier unique to the user's session
if (Cache["userID"] != null)
Cache.Remove("userID");
}
Also, if you want the item in the cache to stay active for the duration of the user's session, you'll need to use a sliding expiration on the item and refresh it with each request. I do this in the OnActionExecuted (ASP.NET MVC only).
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
// Put object back in cache in part to update any changes
// but also to update the sliding expiration
filterContext.HttpContext.Cache.Insert("userID", myObject, null, Cache.NoAbsoluteExpiration,
TimeSpan.FromMinutes(20), CacheItemPriority.Normal, null);
base.OnActionExecuted(filterContext);
}

How can I handle forms authentication timeout exceptions in ASP.NET?

If the session has expired and the user clicks on a link to another webform, the asp.net authentication automatically redirect the user to the login page.
However, there are cases when the user does not click on links to other webforms. For example: edit link in gridviews, when using AutoCompleteExtender with textboxes and the application attempts to get the information, and basically, in every case when a postback is done and the event is not automatically handled by the asp.net authentication.
What is the best way to handle these exceptions?
UPDATE: I have just modified the question title: forms authentication timeout, instead of the initial session timeout. Thanks for making me aware of this difference.
UPDATE: I have just created a new question with the specific problem I am facing: How to handle exception due to expired authentication ticket using UpdatePanel?. Surprisingly, I have not found much information about it. I would really appreciate your help.
This is why many systems include timers on the page to give approximate timeout times. This is tough with interactive pages. You really need to hook ajax functions and look at the return status code, which is a bit difficult.
One alternative is to use code based on the following which runs early in the page lifecycle and perform an ajax redirect to a login page. Otherwise you are stuck trying to intercept the return code from ajax and in asp.net where the ajax is done 'for you' (ie not a more manual method like jQuery) you lose this ease of detection.
http://www.eggheadcafe.com/tutorials/aspnet/7262426f-3c65-4c90-b49c-106470f1d22a/build-an-aspnet-session-timeout-redirect-control.aspx
for a quick hack you can try it directly in pre_init
http://forums.asp.net/t/1193501.aspx
Edit
what is wanted are for forms auth timeouts, not session timeouts. Forms auth timeouts operate on a different scale than session timeouts. Session timeouts update with every request. Forms auth tickets aren't actually updated until half of the time goes by. So if you have timeouts set to an hour and send in one request 25 minutes into it, the session is reset to an hour timeout, the forms auth ticket isnt touched and expires in 35 minutes! To work around this, sync up the session timeout and the forms auth ticket. This way you can still just check session timeouts. If you don't like this then still - do the below and sync up the timeouts and then parse the auth ticket and read its timeout. You can do that using FormsAuthentication.Decrypt - see:
Read form authentication cookie from asp.net code behind
Note that this code requires that upon login you set some session value - in this case its "UniqueUserId". Also change the login page path below to fit yours.
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
//Only access session state if it is available
if (Context.Handler is IRequiresSessionState || Context.Handler is IReadOnlySessionState)
{
//If we are authenticated AND we dont have a session here.. redirect to login page.
HttpCookie authenticationCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (authenticationCookie != null)
{
FormsAuthenticationTicket authenticationTicket = FormsAuthentication.Decrypt(authenticationCookie.Value);
if (!authenticationTicket.Expired)
{
if (Session["UniqueUserId"] == null)
{
//This means for some reason the session expired before the authentication ticket. Force a login.
FormsAuthentication.SignOut();
Response.Redirect("Login.aspx", true);
return;
}
}
}
}
}
If you're using Forms Authentication, the user will be redirected to the login page when the Forms Authentication ticket expires, which is not the same as the Session expiring.
You could consider increasing the Forms Authentication timeout if appropriate. Even to the extent of using a persistent cookie. But if it does expire, there's no real alternative to redirecting to the login page - anything else would be insecure.
One way to deal with Session timeouts is to use Session as a cache - and persist anything important to a backing store such as a database. Then check before accessing anything in Session and refresh if necessary:
MyType MyObject
{
get
{
MyType myObject = Session["MySessionKey"] as MyType
if (myObject == null)
{
myObject = ... get data from a backing store
Session["MySessionKey"] = myObject;
}
return myObject;
}
set
{
Session["MySessionKey"] = value;
... and persist it to backing store if appropriate
}
}
If you're using a master page or a base page, I would add some logic to one of the events in the page lifecycle to check whether the session is new:
protected void Page_Load(object sender, EventArgs e)
{
if (Session.IsNewSession)
{
//do whatever you need to do
}
}

How to Kill A Session or Session ID (ASP.NET/C#)

How can I destroy a session (Session["Name"]) when the user clicks the logout button?
I'm looking through the ASP.NET API Reference on MSDN and it doesn't seem to have much information. It seems rather limited. But I cannot find any other pages for ASP.NET Classes etc.
I have tried:
Session.Abandon(); and
Session.Contents.Remove("Name"); neither of them work. ( I found these in a forum from a Google search)
The Abandon method should work (MSDN):
Session.Abandon();
If you want to remove a specific item from the session use (MSDN):
Session.Remove("YourItem");
EDIT: If you just want to clear a value you can do:
Session["YourItem"] = null;
If you want to clear all keys do:
Session.Clear();
If none of these are working for you then something fishy is going on. I would check to see where you are assigning the value and verify that it is not getting reassigned after you clear the value.
Simple check do:
Session["YourKey"] = "Test"; // creates the key
Session.Remove("YourKey"); // removes the key
bool gone = (Session["YourKey"] == null); // tests that the remove worked
It is also a good idea to instruct the client browser to clear session id cookie value.
Session.Clear();
Session.Abandon();
Response.Cookies["ASP.NET_SessionId"].Value = string.Empty;
Response.Cookies["ASP.NET_SessionId"].Expires = DateTime.Now.AddMonths(-10);
Session.Abandon()
This marks the session as Abandoned, but the session won't actually be Abandoned at that moment, the request has to complete first.
From what I tested:
Session.Abandon(); // Does nothing
Session.Clear(); // Removes the data contained in the session
Example:
001: Session["test"] = "test";
002: Session.Abandon();
003: Print(Session["test"]); // Outputs: "test"
Session.Abandon does only set a boolean flag in the session-object to true. The calling web-server may react to that or not, but there is NO immediate action caused by ASP.
(I checked that myself with the .net-Reflector)
In fact, you can continue working with the old session, by hitting the browser's back button once, and continue browsing across the website normally.
So, to conclude this: Use Session.Clear() and save frustration.
Remark: I've tested this behaviour on the ASP.net development server. The actual IIS may behave differently.
Session.Abandon() this will destroy the data.
Note, this won't necessarily truly remove the session token from a user, and that same session token at a later point might get picked up and created as a new session with the same id because it's deemed to be fair game to be used.
You kill a session like this:
Session.Abandon()
If, however, you just want to empty the session, use:
Session.Clear()
Session.Abandon()
is what you should use. the thing is behind the scenes asp.net will destroy the session but immediately give the user a brand new session on the next page request. So if you're checking to see if the session is gone right after calling abandon it will look like it didn't work.
Session["YourItem"] = "";
Works great in .net razor web pages.
Session.Abandon(); did not work for me either.
The way I had to write it to get it to work was like this. Might work for you too.
HttpContext.Current.Session.Abandon();

Categories