The previous version of this answer provides a simple source for resolving a question that no longer exists.
The scenario was that he wanted to be notified before the session timed out so that the action could be taken.
It is not clear if this is an asp.net session or forms authentication ticket, but this is actually the same problem.
Basically this is managing async session state without starting a session / ticket update. A common desire for ajax applications.
The solution is quite simple, but not quite straightforward. There are many problems to solve, but I chose a solution that works reliably for both simple session state and forms authentication.
It consists of a very light httpmodule and an accompanying client script library, and no more than 50 or 60 effective lines of code.
The strategy is to provide an http endpoint that can request the expiration status of a session or form ticket without updating them. The module just sits on the front of the pipeline and serves a couple of βvirtualβ endpoints with javascript dates and a very simple js lib to make calls.
Demo and source are here: AsynchronousSessionAuditor
Some of you are wondering why I will be worried about this, but probably more of you say hell, yes, what a pain in the patch. I know that in the past I came up with fragile smelly workarounds, and I am very pleased with that.
It can be used in a standard postback application, or rather in an ajax application. Also ... You can learn more about the Http request life cycle here and here . If interested, learn more about using raw xmlhttp for asp.net endpoints here
Abbreviation of the previous spike code. Check the change history if you are interested.
Here are the relevant source files. The full reference implementation is available at the link above ....
HttpModule
Client library
// <copyright project="AsynchronousSessionAuditor" file="AsynchronousSessionAuditor.js" company="Sky Sanders"> // This source is a Public Domain Dedication. // http://spikes.codeplex.com // Attribution is appreciated. // </copyright> var AsynchronousSessionAuditor = { /// this script really should be served as a resource embedded in the assembly of the module /// especially to keep the keys syncronized pollingInterval: 60000, // 60 second polling. Not horrible, except for the server logs. ;) formsAuthAuditKey: ".formsauthticket", // convenience members aspSessionAuditKey: ".aspnetsession", errorCallback: function(key, xhr) { /// <summary> /// Default behavior is to redirect to Default and provide the xhr error status text /// in the loggedout query param. /// /// You may replace this default behaviour with your own handler. /// eg AsynchronousSessionAuditor.errorCallback = myMethod; /// </summary> /// <param name="key" type="String"></param> /// <param name="xhr" type="XMLHttpRequest"></param> window.location = "Default.aspx?loggedout=Error+" + xhr.statusText; }, timeoutCallback: function(key, xhr) { /// <summary> /// Default behavior is to redirect to Default and provide the key value /// in the loggedout query param. /// /// You may replace this default behaviour with your own handler. /// eg AsynchronousSessionAuditor.timeoutCallback= myMethod; /// </summary> /// <param name="key" type="String"></param> /// <param name="xhr" type="XMLHttpRequest"></param> window.location = "Default.aspx?loggedout=" + key; // or just refresh. you will be sent to login.aspx }, statusCallback: function(value) { /// <summary> /// Default behavior is to do nothing, which is not very interesting. /// This value is set when AsynchronousSessionAuditor.init is called /// </summary> /// <param name="value" type="String"> /// The responseText of the audit request. Most certainly is a JavaScript Date /// as a number. Just cast to date to get the requested expiration dateTime. /// eg var exp = new Date(parseFloat(value)); if (isNaN(exp)){this should never happen} /// </param> window.location = "Default.aspx?loggedout=" + key; // or just refresh. you will be sent to login.aspx }, createXHR: function() { /// <summary> /// This xhr factory is not the best I have see. /// You may wish to replace it with another or /// use your favorite ajax library to make the /// call. /// </summary> var xhr; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { xhr = new ActiveXObject('Microsoft.XMLHTTP'); } else { throw new Error("Could not create XMLHttpRequest object."); } return xhr; }, auditSession: function(key) { /// <summary> /// Make a request that will be serviced by the audit module to determine the /// state of the current FormsAuthentication ticket or Asp.Net session /// /// The return value is a JavaScript date, in numeric form, that represents the /// expiration of the item specified by key. /// Just cast it to date, ie new Date(parseFloat(xhr.resposeText)) /// </summary> /// <param name="key" type="String"> /// the server key for the item to audit. /// /// use ".formsauthticket" to get the expiration dateTime for the forms authentication /// ticket, if any. /// /// use ".aspnetsession" to get the expiration of the current ASP.Net session. /// /// Both have convenience members on this object. /// </param> var xhr = AsynchronousSessionAuditor.createXHR(); xhr.open("GET", key, true); xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status != 200) { AsynchronousSessionAuditor.errorCallback(key, xhr); } else { var timeout = parseFloat(xhr.responseText) if (isNaN(timeout) || (new Date(timeout) < new Date())) { AsynchronousSessionAuditor.timeoutCallback(key, xhr); } else { AsynchronousSessionAuditor.statusCallback(xhr.responseText); } } } }; xhr.send(null); }, init: function(key, statusCallback) { // set the statusCallback member for reference. AsynchronousSessionAuditor.statusCallback = statusCallback; // check right now AsynchronousSessionAuditor.auditSession(key); // and recurring window.setInterval((function() { AsynchronousSessionAuditor.auditSession(key) }), AsynchronousSessionAuditor.pollingInterval); } }; function callScriptMethod(url) { /// <summary> /// /// Simply makes a bogus ScriptService call to a void PageMethod name DoSomething simulating /// an async (Ajax) call. /// This resets the session cookie in the same way a postback or refresh would. /// /// The same would apply to a ScriptService enabled XML Webservice call. /// </summary> var xhr = AsynchronousSessionAuditor.createXHR(); xhr.open("POST", url, true); xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status != 200) { alert("script method call failed:" + xhr.statusText); } } }; xhr.setRequestHeader("content-type", "application/json"); var postData = null; xhr.send(postData); }
Using
<script src="AsynchronousSessionAuditor.js" type="text/javascript"></script> <script type="text/javascript"> function reportStatus(value) { </script>