Sep 19, 2012, 3:36 PM
[CLOSED] DirectMethod heartbeat task and State management
Hi,
I'd like to be able to examine the Request object on the server to find out which DirectMethod has initiated it. I'm curious how to approach it. Every page in my application is inherited from the BasePage class, which has the overridden OnInit method. In there, my logic inspects the Session to determine if it's expired or not causing the redirect if needed.
What I'm trying to accomplish here is to create a little heartbeat task using TaskManager that polls the server every SessionTimeout interval using DirectMethod to see if the Session is still alive. There's a slight logistics problem here. The heartbeat call by itself inadvertently revives the otherwise idle Session extending its validity until at least another heartbeat cycle.
My thought process is to provide a unique marker for the heartbeat Request so that it can be analyzed in the OnInit. If a Request is NOT initiated by the heartbeat, I can use a custom Session variable, e.g. "LastAccessed", to store the timestamp when it was last accessed. If the Request is indeed initiated by the heartbeat task, I should then check the value of the "LastAccessed" variable and adjust the task interval accordingly. For example, If the last user Request was initiated 12 minutes ago with the SessionTimeout of 20 minutes, the next poll by my heartbeat task should occur in 20-12=8 minutes. If it then detects that the value of the LastAccessed variable hasn't changed, it should invalidate the session and cause the redirect after its return to the client even if the session is technically alive.
The simplest case occurs when the heartbeat hits the server and the session has truly expired. Then, the logic in OnInit redirects the user to a designated web page.
Here's the code snippets. Does my logic make sense? Please advise if there's an established pattern to achieve this behavior or if you need more information.
BasePage.cs
I'd like to be able to examine the Request object on the server to find out which DirectMethod has initiated it. I'm curious how to approach it. Every page in my application is inherited from the BasePage class, which has the overridden OnInit method. In there, my logic inspects the Session to determine if it's expired or not causing the redirect if needed.
What I'm trying to accomplish here is to create a little heartbeat task using TaskManager that polls the server every SessionTimeout interval using DirectMethod to see if the Session is still alive. There's a slight logistics problem here. The heartbeat call by itself inadvertently revives the otherwise idle Session extending its validity until at least another heartbeat cycle.
My thought process is to provide a unique marker for the heartbeat Request so that it can be analyzed in the OnInit. If a Request is NOT initiated by the heartbeat, I can use a custom Session variable, e.g. "LastAccessed", to store the timestamp when it was last accessed. If the Request is indeed initiated by the heartbeat task, I should then check the value of the "LastAccessed" variable and adjust the task interval accordingly. For example, If the last user Request was initiated 12 minutes ago with the SessionTimeout of 20 minutes, the next poll by my heartbeat task should occur in 20-12=8 minutes. If it then detects that the value of the LastAccessed variable hasn't changed, it should invalidate the session and cause the redirect after its return to the client even if the session is technically alive.
The simplest case occurs when the heartbeat hits the server and the session has truly expired. Then, the logic in OnInit redirects the user to a designated web page.
Here's the code snippets. Does my logic make sense? Please advise if there's an established pattern to achieve this behavior or if you need more information.
BasePage.cs
public partial class BasePage : System.Web.UI.Page
{
override protected void OnInit(EventArgs e)
{
//initialize our base class (System.Web,UI.Page)
base.OnInit(e);
//check to see if the Session is null (doesnt exist)
if (Context.Session != null)
{
//check the IsNewSession value, this will tell us if the session has been reset.
//IsNewSession will also let us know if the users session has timed out
if (Context.Session.IsNewSession)
{
//now we know it's a new session, so we check to see if a cookie is present
string cookie = Request.Headers["Cookie"];
//now we determine if there is a cookie does it contains what we're looking for
if ((null != cookie) && (cookie.IndexOf("ASP.NET_SessionId") >= 0))
{
if (Request.UrlReferrer != null)
Response.Redirect(baseURL + "/SessionExpired.aspx");
}
}
else
{
// Logic to inspect the Request?? object to see if it's initiated by DoHeartbeat()
bool isHeartBeat = false;
/*
NameValueCollection headers = base.Request.Headers;
string requestedWith = headers["X-Requested-With"];
if (!String.IsNullOrEmpty(requestedWith) && requestedWith.Equals("XMLHttpRequest"))
isHeartBeat = true;
*/
if(isHeartBeat)
{
DateTime lastUpdated = Session["LastAccessed"] as DateTime;
// Convert to milliseconds to get the interval when the Heartbeat service should run next time
long updatedInterval = DateTime.Now.Ticks - lastUpdated.Ticks;
Session["UpdatedInterval"] = updatedInterval;
}
else
{
// Set the value of Session["LastAccessed"] because this request is initiated NOT by HeartBeat
Session["LastAccessed"]=DateTime.Now;
}
}
}
}
}
Default.aspx.cs// Non-static method to ensure that page lifecycle is followed
[DirectMethod]
public long DoHeartbeat()
{
long updatedInterval=Convert.ToInt64(Session["UpdatedInterval"]);
return updatedInterval;
}
Default.aspx<ext:TaskManager ID="TaskManager1" runat="server">
<Tasks>
<ext:Task TaskID="TaskHeartbeat" Interval="120000" AutoRun="true">
<Listeners>
<Update Handler="X.DoHeartbeat({success : function(result){TaskManager1.tasks[0].interval=result;});" />
</Listeners>
</ext:Task>
</Tasks>
</ext:TaskManager>
Last edited by Daniil; Sep 21, 2012 at 6:12 AM.
Reason: [CLOSED]