Can Session_End fire on window close? (ASP.NET) - asp.net

I am putting an "online" counter on a website, and I have run into these two contradicting sources.
This one (I am using this example code):
http://aspdotnetfaq.com/Faq/How-to-show-number-of-online-users-visitors-for-ASP-NET-website.aspx
...says that:
Also when user closes his browser or does not click on any links in
our website, session expires, and our "OnlineUsers" global variable
is decreased.
However, this one:
http://www.velocityreviews.com/forums/t383710-session-end-guarantee.html
...says that:
Closing the browser window, or browsing to another site will NOT cause
Session_End to fire, at least, not straightaway - the server has
absolutely no way of knowing what happens on the client machine until
it gets another HttpRequest from it. In this instance, Session_End
will fire when the session times out naturally.
I have tested and it seems that Session_End DOES NOT fire.
I basically want you guys to confirm or comment on this.
Is it possible to update the online counter on browser-close?

The second is true
Closing the browser window, or browsing to another site will NOT cause
Session_End to fire, at least, not straightaway - the server has
absolutely no way of knowing what happens on the client machine until
it gets another HttpRequest from it. In this instance, Session_End
will fire when the session times out naturally.
Session time out is 20 minutes by default. You can confirm this by not doing any activity on your website for 20 min.

Your two links are not contradictory. The first link is poorly worded, but it basically says what the second link says. It would be easier to understand if it were written like this:
Also when user closes his browser or does not click on any links in our website (after a period of time) the session will expire, and our "OnlineUsers" global variable is decreased.
Also note that Session_End may not always fire, especially if the session is killed or bounced (for example, if you update the web.config, the worker process recycles, or in some cases an uncaught exception occurs).

As is pointed out later in the first link posted the Session_End event fires after the session timeout expires. If the user who is associated with a session sends no requests to the server before the session timeout value expires the session_end event will be fired and the session will be removed from memory.
MSDN for asp.net session state: http://msdn.microsoft.com/en-us/library/ms178581.aspx

Related

Finding time until timeout fires in asp.net

First of all, let me ask this:
Let's say that a web application has its timeout set to 10 minutes. For some reason, the user is idle. If he/she returns and press any key or moves the mouse, it resets the timeout? Or it is based on the last time it went to the server?
And now the second question: is there a way to find the time until the user gets logged off due to innactivity?
From MSDN:
The Timeout property specifies the time-out period assigned to the
Session object for the application, in minutes. If the user does not
refresh or request a page within the time-out period, the session
ends.
So in answer to your question, the timeout is reset if the user sends a request to the server by either navigating to another page or refreshing the current page (or possibly by using some form of AJAX keep-alive method (See this question)).
This article on Code Project provides a pretty good overview of Sessions within ASP.net
For your second question, this gets a little complex as the session timeouts are managed by IIS so your page has no idea how much longer the session will be valid for. I have seen examples where another timer is placed with in the page itself and when this reaches a certain low value the user is warned that their session is about to expire. The page could then refresh (resetting the session timeout value in IIS) and the user wouldn't be logged out / lose their session.
However, this will require the session timeout value that is configured is kept in sync with the value configured in the JavaScript function.

Access Session on End?

I am trying to "log" forcefully when a user has been inactive and or the session has ended (either by inactivity or more importantly, when the browser has closed).
I dont want to use any silly AJAX solution to perform a post every few minutes for "im alive" or call when the browser is closed.
I was under the impression that if you store an object in Session, and you reach the Session_End event, then you will not be able to gain access to anything stored in Session as its ended.
But from some testing I have done, it appears that this is probably the last chance you can obtain access to the object.
Could this be true? is it reliable?
using ASP.NET 4.0 here.
Typically there are two things done.
The first is that a javascript timer is added to the client, not as a heartbeat, but rather as a reminder. If they are close to the session ending, then it simply says "session is about to end. Are you still there?" If so, then it does the "silly" post to ensure the server keeps the session going. This is purely to be nice to your users.
The second (and point of your question) is that you put something in session_end in order to clean up the session. Reliable? well.. most of the time.
Session_End won't run if the app pool is recycled. However, assuming the app pool is ok then yes it will execute when the session expires. The app pool can be recycled for a LOT of reasons ranging from the app crashing to exceeded memory usage to simply because it's been a while since the last reset. This is configurable in IIS.
Would I trust session_end? No. Not 100%. Of course, I wouldn't put anything inside of a session object that would require me to trust it 100% anyway.
For logging the timeout You can use the Global events to log at timeout. See this link for order of events http://www.techrepublic.com/article/working-with-the-aspnet-globalasax-file/5771721

Logout solution (ASP.NET)

I programmed a web site, prepared a login mechanism(via textbox, not Login tools), users want to logout, they click logout button. However, my problem is that if users don't click logout button or close web page or switch another one, How can I understand this situation?
According my mechanism, when users logout ,in DB some insertion and delete operation are making.
I also want to do this with closing page,switch another one.
Thanks.
It sounds like you're doing a DB operation on logout, and when people just navigate away without clicking the logout button, the code doesn't fire.
In your global.asax, take a look at session_end. Maybe you can put your operation in there.
protected void Session_End(Object sender, EventArgs e)
{
// Your code goes here. Since your logout code probably relied on the user being
// logged in, you might end up checking Request.IsAuthenticated here. Why? Because
// this event fires any time a session ends -- even if the user is not logged in!
}
Note that if you use this, it actually fires when the IIS session ends, not when the browser closes. By default the session times out after 20 minutes of inactivity.
Once you implement this, you could have your logout page call Session.Abandon, which will trigger Session_End. That seems clean to me.
Here's an MSDN link with some more details on session events: http://msdn.microsoft.com/en-us/library/ms178583.aspx
Session end is probably your best bet as previously mentioned, but if you're paranoid, you can put some javascript/AJAX on your page that pings your server every X seconds to basically say "I'm still here". Then if they leave, instead of waiting the whole 20 minutes or so for the session to end, you can know within X seconds that they've left, since they're not pinging anymore.
If your session timeout is 20 minutes you will only detect after 20 minutes that the session has ended = the user has left your page. You can detect the session end in the global.asax session_end like Brian describes.
If you want to detect someone leaving your page earlier - say after a minute, you could reduce the session timeout to 1 minute.
The problem is then, if the user doesn't do anything on your page - no post back to the server - his session will timeout despite him still viewing your page.
To get around this you could use a keep alive mechanism. Your Page would call the server regularly in the background as long as the user views your page. This can be done with AJAX Javascript or oher mechanisms like hidden iFrame.
See for example: ASP.NET AJAX and keeping the Session alive - What is the standard way to do it?
I am not entirely sure, but I think one way this is implemented is to not set an expiration on a cookie, which will cause it to be a session cookie that is lost when the browser is closed. Since your session cookie typically contains the session key, then they will essentially be starting a new session when they open up a browser again.
When I make users system, I add to database table with users that are login (something like session) and i gave them timestamp. Every refresh of site I run query to delete users with timestamp older then 30 minutes. This is very easy solution, maybe there is better way.
might want to check out the events in global.asax. You can update the db with the session_end event. You can also use the beginrequest event which is fired on each page and control (you'll get multiple hits per page if you have multiple controls). You could also put something in your page_load event.

How to abandon session if user X's out of browser?

Is there a way to do a Session.Abandon() when the user just kills the session by X'ing out with the little red X box in the upper right corner? I am seeing situations where after an "X out", the user comes back in and it seems like session variables are still present? I guess explorer keeps them intact? (I am unsure of this).
You can try doing an AJAX type callback in the OnUnload event - however, as someone else mentioned you'd have to be aware of other tabs being open (not easy), and it still won't guarantee you get that event.
There's a combination of things to do to get a similar type of effect.
Session Cookie should have a null/empty expiry time. This ensures the browser deletes the session from it's end after the browser is closed.
The ASP Session can be set with a short SessionState timeout value. This means if there's no client activity within that period, the Session will expire.
The side effect of this is that if a user is just looking at the site, and not performing activity (regardless of whether the browser is still open) - the session can expire.
This can be worked-around by having a Javascript timer periodically ping back to the server with an AJAX call or similar. The side effect of THIS is that it generates more site traffic.
The server is typically not aware of such events on the client. The only way the server can be notified about anything is if there is a request sent back to it. I guess you could create such a notification in a JavaScript, but then you should also keep in mind that the session in mind that the session is not per-page but (usually) per user, which means that you would need to keep track of how many tabs/windows the user has opened so that you don't kill the session when you should not.
Personally, I usually try to design the web apps so that they live well with the default handling of sessions, either providing a specific "Logout" command that will kill the session, or simply let it hit the timeout and die.

ASP.NET Session_End called immediately after Session_Start after a session timeout

I have handlers for my Session_Start and Session_End events. When I first start the application, everything works fine. If I leave the session and the standard timeout occurs, I watch my Session_End throw. I'm expecting that behavior.
Let's say though, I come back after the timeout and refresh a page. The Session_Start method runs, but then immediately the Session_End method runs. I'm expecting another 15 minutes of idleness between Session_Start and Session_End.
What would be the problem?
EDIT: Yes, same session id.
EDIT 2: Cookies look like they are supposed to expire at the end of session. Not sure why I keep getting this loop of Session_Start/Session_End. I've also tried calling Session.Abandon() from Session_End, and that didn't work. This is running off the ASP.NET Development server too. I haven't tried it on a real IIS server yet.
It's a bit late to answer but it might be useful to other users who have the same problem.. I've experienced the same behavior as you've seen: Session_Start() and Session_End() are called for every request after the first timeout and the SessionID is always the same:
I've run the same code with ASP.NET 4.0 and the problem is gone.
As a workaround in ASP.NET 2.0/3.5, just put anything in the session collection (Session["dummy"] = "dummy"), and Session_Start() and Session_End() will behave normally.
.Net does some funky things with their session cookies, esp. in conjunction with Forms auth. I'm just guessing, but I'd think that the client is hanging on to the cookie, and re-sending it to the server even after its invalid, which (I'm guessing here) might trigger a restart of the session, at which point it recognizes that its invalid and trashes it, causing the session end.
Try:
Making sure your cookies are set to expire properly
Calling Session.Abandon() and FormsAuthentication.SignOut()
Not sure if that helps, but FWIW.
For anyone with the same problem.
The answer given by Alex B saved me.
This no longer happens on 4.0, but if you put something in the Session inside the Session_Start handler, this cuts the Session_Start -> Session_End circle, and you don't even have to delete cookies.
Can you verify that the events are firing for the same session ID?
This is a duplicate of this question.
It's because of the way ASP.NET 2.0/3.5 handles sessions based on whether it's in use. In normal circumstances it does not try to persist a session until the first time it's used and therefore does not issue a session cookie (if it doesn't exist). The first time session is used, a session is created on the server and a session cookie issued.
Now when a previous session is restarted but not used, then ASP.NET gets a little confused. It tries to abandon the unused (restarted) session immediately as it's not required, which raises an early Session_End. However it does not delete the pre-existing session cookie, and hence every subsequent request repeats the sequence, restarting and then terminating the session until the cookie is deleted or the session is used.
In .Net 4.0 this behaviour has changed, and the event no longer fires in this case.

Resources