I literally stumbled across this solution while creating the WSMQ Instant Messenger demo that I posed about last week. My problem was that I needed a way to log users out of the chat application when they closed their browser window. Since I was storing my list of users in the application, they'd hang around indefinitely unless I manually pulled them out, or until the worker process restarted.
Then it occurred to me that this may also work as a mechanism to automatically time out a users session when they close their browser. On a big website, you could have hundreds of sessions sitting around taking up memory, that aren't being used. Depending on what you've decided to load the session up with, this could be a resource hit for your web server. By default, these sessions will timeout after 20 minutes, but with this method, you can time them out as soon as the user closes their browser.
The solution requires using this Remote Scripting Java Script library from Alvaro Mendez that allows you to call any method on an ASP.NET page from within client-side Java Script. It also requires that pages in your site inherit from a PageBase class (which is good practice and hopefully you're doing this anyway).
Step 1 - Add the RemoteScripting.cs file to your project
This just has to live somewhere in your project, or in a referenced DLL. If you have a [Your Namespace].Web project, this would be a good place to put this so that you can re-use it across web applications.
Step 2 - Give RemoteScripting a chance to handle each request
You can do this in a variety of ways, but one sure way is to add the following line of code to your PageBase's OnInit method. What this will do it let RemoteScripting handle the request if it needs to. Now, there is a bit of a trade off here, you are adding extra cycles to each request, so you may want to consider the overall payoff here. It's not much processing if there was no remote method called.
protected override void OnInit(EventArgs e){
// If it was called invoke the remote method and get back to the client
RemoteScripting.InvokeMethod(this);
}
Step 3 - Add an EndSession method to your PageBase Class
This will be the remote method that gets called when the browser window is closed.
public void EndSession() {
// This will call the application session on end method.
this.Session.Abandon();
}
Step 4 - Include the rs.js Client Side JavaScript Library on your Pages.
You've got to add the rs.js script which comes with the RemoteScripting to each page. You could do this in the ASPX code, or pro grammatically in your PageBase. A good place to do this would be in your OnPreRender method.
Step 5 - Add a JavaScript event handler to your ASPX page's onbeforeunload event.
Unfortunately, the following script only works with IE. If anyone can figure out how to get it to work with Firefox, that would be awesome. It at least doesn't cause problems in FireFox, so it should be relatively harmless...
// Wire up the onbefore unload event
window.onbeforeunload = EndSession;
// Close all open chat windows, and call the remote method to logout of the application
function EndSession()
{
// Get the real ASPX page name
var sPath = window.location.pathname;
var sPage = sPath.substring(sPath.lastIndexOf('/') + 1);
if(sPage == '') sPage = "Default.aspx";
// They're in a popup window, don't kill the session here!
if(window.opener != null) return;
// Only want to run the endsession for IE, no way to tell currently if it's not IE and
// the window is closing
if(window.event != null) {
var abssize = document.body.offsetWidth-30;
if (window.event.clientY < 0 && event.clientX >= abssize) {
RS.Execute(sPage, "EndSession");
}
}
}
That's it! Now when someone closes their browser, the remote method should be called, and the session gets killed. I'd recommend that if you try to do this, you do some debugging to make sure that you have everything wired up correctly, since there's no UI component to this.
Good Luck!
-Brendan
Posted
Tue, Jan 25 2005 8:30 AM
by
Brendan Tompkins