The Never Ending Ooze

Friday, June 30, 2006

Using AJAX in ASP.NET

If some one has ever used Google Suggest, then they have seen AJAX (Asynchronous Javascript and XML) in action. I have been using Google Suggest for quite some time now and never bothered to ponder over how this thing works. I had been discussing this with my colleague Sanjeeva for quite some time but really came to know more about the technology when an issue came up in my current project.(happens with me all the time-when I use it, I get to know more. :-) )

Google has been vigorously using AJAX lately-take Google Maps or Google Suggest-both are based on the fundamentals on AJAX and work beautifully. I really appreciated the idea of the search engine telling me what to search ;-) And what more-these applications are doing beautifully-check out these analysis of the same- Gmail, Google Suggest and Google Maps.

The issue is as follows -- We have a web application which displays beautiful reports to the user apart from having some other nitty-grities. Apart from the graph being displayed on the page, there is a plethora of information being shown to the user. Then the customer asked us to add a filter to the chart so that the user can get a new chart based on the filter chosen. Doing a postback would have been good and beauifully traditional, BUT then the entire page would be loaded again and this would make the user mad waiting for the entire information to be loaded up again. Just to make myself clear, when I say 'traditional' approach, I mean that any user action, say a button click) in the web page would lead to a postback (if configured that way, of course). So effectively it means a HTTP request would be sent to the server. On receiving the request, the server would take appropriate action and return a rendered HTML page back to the waiting browser. But the question that is obvious out here is-what if the page is very heavy? Wont the page take a lot of time to load again when all the user required was something refresh the chart when he/she changes some display criteria? How many times have you banged your head on the table, when you select 'India' in your drop down and the page is posted back to fetch all the states that are a part if the Indian Republic? Why dont the application developers just send the states back to the browser when the country is selected? Why do they have to load the entire page again? Quite obvious questions and these are what came to my mind...

Here is where we thought of taking help of AJAX.

An AJAX implemented web page removes all this HTTP request-response pain by adding a sort of layer in between. AJAX allows the user to use JavaScript to send XMLHTTPWebRequest to the server by making HTTP requests (GET/POST) without reloading the page. Basically, it is just old wine in a new bottle since technologies like XMLHTTPRequest etc were already there in the market for quite some time when Mcrosoft introduced it in IE 5.0 and Apple in Safari 1.2 and Mozilla in Firefox 1.0 onwards. The server handles the request and sends a response which MAY NOT be XML-it can be something as simple as comma separate list or simple string.

A couple of Google searches later I was ready with a fully functional AJAX implemented web page.

This is the javascript that was added to the aspx page --

var xmlHttp;
var requestURL = 'some aspx page made to handle the ajax request';
var is_ie = (navigator.userAgent.indexOf('MSIE') >= 0) ? 1 : 0;
var is_ie5 = (navigator.appVersion.indexOf("MSIE 5.5")!=-1) ? 1 : 0;
var is_opera = ((navigator.userAgent.indexOf("Opera6")!=-1)(navigator.userAgent.indexOf("Opera/6")!=-1)) ? 1 : 0;
//netscape, safari, mozilla behave the same???
var is_netscape = (navigator.userAgent.indexOf('Netscape') >= 0) ? 1 : 0;

function show_data(strName)
{
alert(strName);
//Append the query strings to search for to the requestURL

var url = requestURL + '?q=' + strName + '&ajax=1&dummy=' + new Date().getTime();

alert(url);
//Create the xmlHttp object to use in the request
//stateChangeHandler will fire when the state has changed, i.e. data is received back
// This is non-blocking (asynchronous)

xmlHttp = GetXmlHttpObject(stateChangeHandler);

//Send the xmlHttp get to the specified url
xmlHttp_Get(xmlHttp, url);
}

//stateChangeHandler will fire when the state has changed, i.e. data is received back

// This is non-blocking (asynchronous)

function stateChangeHandler()
{
//readyState of 4 or 'complete' represents that data has been returned

if (xmlHttp.readyState == 4 xmlHttp.readyState == 'complete')
{
//Gather the results from the callback
var str = xmlHttp.responseText;
var temp = new Array();
temp = str.split(',');
//alert(str);
//Populate the innerHTML of the div with the results

document.getElementById('SOMEHTMLIMAGECONTROL').src = temp[0];
}
}

// XMLHttp send GET request

function xmlHttp_Get(xmlhttp, url)
{
xmlhttp.open('GET', url, true);
xmlhttp.send(null);
}

function GetXmlHttpObject(handler)
{
var objXmlHttp = null;
//Holds the local xmlHTTP object instance
//Depending on the browser, try to create the xmlHttp object

if (is_ie)
{
//The object to create depends on version of IE
//If it isn't ie5, then default to the Msxml2.XMLHTTP object

var strObjName = (is_ie5) ? 'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP';

//Attempt to create the object

try
{
objXmlHttp = new ActiveXObject(strObjName);
objXmlHttp.onreadystatechange = handler;
}
catch(e)
{
//Object creation errored
alert('IE detected, but object could not be created. Verify that active scripting and activeX controls are enabled');
return;
}
}
else if (is_opera)
{ //Opera has some issues with xmlHttp object functionality

alert('Opera detected. The page may not behave as expected.');
return; }
else { // Mozilla Netscape Safari
objXmlHttp = new XMLHttpRequest();
objXmlHttp.onload = handler;
objXmlHttp.onerror = handler;
} //Return the instantiated object
return objXmlHttp; }



The function show_data is called on some event say the change of drop down or click of a button.

The changes that were done in the code behind are --

string ajax = "";
ajax = Request.QueryString["ajax"];
if(ajax != null)
{
Response.Clear();
Response.Write(imageURL + "," + imageBarURL);
//imageBarURL is the path to the image which will be displayed on the webpage.
Response.End();
}

You would notice a small thing in the javascript above-"&dummy=' + new Date().getTime();" This was done so that the caching effect of the browser can be done away with. I know it is a hack-but it works.

A better way would be to expire the cache on the parent web page or user control as follows --
//Avoid the caching effect in Internet Explorer
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Buffer = true;
Response.ExpiresAbsolute = DateTime.Now.Subtract(new TimeSpan(360, 0, 0, 0)); Response.Expires = -1;
Response.Cache.AppendCacheExtension("max-age=0, no-store, must-revalidate"); Response.AddHeader("Pragma", "no-cache");

The above works on IE 5.0 and above, Mozilla Firefox, Safari, Netscape 7.0 and above.

0 Comments:

Post a Comment

Links to this post:

Create a Link

<< Home