advanced web statistics

IRequiresSessionState and Dynamic Data in Static Pages

9/20/2007 5:11:41 PM

Just learned something really cool about Generic Handlers (.ashx).  There is a cool interface called IRequiresSessionState that you can implement to gain access to session data. This interface isn't new and a quick Google search will net you some great blog entries about it.  For me, this interface opened up my eyes in that I now use these Generic Handlers for asynchronous callbacks. Now you can read & write Session-state values from static HTML pages using JavaScript.

When would you ever need to use this? High-traffic site that needs to be cached? Integrating bits of dynamic information within static pages (large existing sites), etc..  This technique could also be used to read querystring values from non .NET sites (php, asp, jsp, etc...).  Again, think being able to add an ASP.NET Generic Handler to an existing site (granted it's hosted on a server that has the .NET Framework installed) and read Querystring information from non-.NET pages.

First here's the Handler.ashx file.  What I'm doing here is examing the current request and checking to see if my session values of A & B (lame I know) exist.  If not I'm simply going to return "none" to the client.  In a real-world scenario I would probably return an empty string but will do this for the example.  You need to SEE it work. :-)

I will call this page from a static HTML page (via xmlHttpRequest*) and populate a textbox with the value and also set this session variable from the same textbox's onblur event. In a nut-shell I am exchanging session data between a static (HTML) and dynamic (.aspx) page.  There is a demo (animated) to show this.

* should be renamed webRequest!

<%@ WebHandler Language="C#" Class="Handler" %>

using System.Web;
using System.Web.SessionState;

public class Handler : IHttpHandler , IRequiresSessionState
{
   public void ProcessRequest (HttpContext context) 
   {
      context.Response.ContentType = "text/plain";
      context.Response.Cache.SetCacheability(HttpCacheability.NoCache);

      string item = context.Request.QueryString["item"] ?? "";
      string update = context.Request.QueryString["update"] ?? "";

      switch (item)
      {
         case "A":
            
            if (!string.IsNullOrEmpty(update))
               context.Session["A"] = update

            object a = context.Session["A"];   
            context.Response.Write(a != null ? (string) a : "none");

            break;

         case "B":

            if (!string.IsNullOrEmpty(update))
               context.Session["B"] = update

            object b = context.Session["B"];
            context.Response.Write(b != null ? (string) b : "none");

            break;
      }
   }

   public bool IsReusable 
   {
      get { return false; }
   }

Here is the code markup for the "static" HTML page.  The JavaScript actually belongs in an external .js file that is referenced but in the interest of time and for educational purposes I put the JavaScript between my head tags.

<html>

<head>
<
title>Handler Example</title>

<script type="text/javascript" language="javascript">

function ajaxFunction(item, update, elementId)
{
   var ajaxRequest = null;
   var url = update != null ? "Handler.ashx?item=" + item + "&update=" + update : "Handler.ashx?item=" + item;

   try { ajaxRequest = new XMLHttpRequest(); }
   catch (e)
   {
      try { ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP"); } 
      catch (e) 
      {
         try { ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP"); }
         catch
(e)
         {
            alert("your browser sucks!");
         
            return false;
         }
      }
   }

   ajaxRequest.onreadystatechange = function()
   {
      if(ajaxRequest.readyState == 4)
      {
         var responseValue = ajaxRequest.responseText;
         document.getElementById(elementId).value = responseValue;
      }
   }

   ajaxRequest.open("GET", url, true);
   ajaxRequest.send(null);
}

function populateSessionValues()
{
   ajaxFunction("A", null, "textA");
   ajaxFunction("B", null, "textB");
}

function onBlurEvent(item, elementId)
{
   var newValue = document.getElementById(elementId).value;
   ajaxFunction(item, newValue, elementId);
}

</script>

</head>

<body onload="populateSessionValues()">

<div style="margin-bottom: 10px;">
<
label>A Value</label>
<
input type="text" id="textA" onblur="javascript:onBlurEvent('A', 'textA')" />
</
div>

<div style="margin-bottom: 10px;">
<
label>B Value</label>
<
input type="text" id="textB" onblur="javascript:onBlurEvent('B', 'textB')" />
</
div>

<div>
<
a href="handlerExample.aspx" target="_top">Back to dynamic page</a>
</
div>

</body>
</
html>

For the demo I create a handlerExample.aspx that simply reads the values from the Session for A & B. When I press the button it resets the session values to "Will" and "Asrari" and then the link directs to the static page. On that page you should see that the session changes actually took place. The textboxes are populate with Session data via asynchronous request. Now to bring it all together with the demo!

Here's the code-behind for handlerExample.aspx.

protected void Page_Load(object sender, EventArgs e)
{
   string a = Session["A"] != null ? (string) Session["A"] : "none";
   string b = Session["B"] != null ? (string) Session["B"] : "none";

   Response.Write(string.Format("{0}<br />{1}", a, b));
}

protected void button1_Click(object sender, EventArgs e)
{
   Session.Add("A", "Will");
   Session.Add("B", "Asrari");

   Response.Write("<br />Added A = Will, and B = Asrari to Session<br />");

Now time for the demo (seriously!).

IRequiresSessionState Demo

Important
On a scale of 1-10 (1 not important and 10 being very important) setting Cacheability to NoCache is about a 75 ESPECIALLY with IE.  The other option is to use POST as I am 95% positive those aren't cached.

The possibilities are endless.  You are also not limited to simply displaying data in a textbox, label, alert, etc...  You can context.Response.Write() HTML to display formatted HTML to the client.  To do this with a div with id divHTMLGoesHere you just do the following:

document.getElementById("divHTMLGoesHere").innerHTML = "";

Easy!

AJAX, C#, JavaScript

kick it on DotNetKicks.com

Leave a Comment

   

  Enter the text to proceed!