Making AJAX calls from a .NET web page - Part 2
Continuation of Part 1
AJAX sample code - calling from a .NET page with C#
Now the good stuff. How do we implement AJAX in our .NET pages? The answer is surprisingly and pleasantly simple, as it turns out, and is not actually particular to any one scripting language, be it C#, php, perl or whatever.
The secret to AJAX is the XMLHttpRequest object. Unfortunately, it has not been implemented in a totally consistent manner across browsers (what else is new?), but as it turns out, the code branching logic needed to overcome this problem is not bad at all. All we have to do is test for the existence of the appropriate object with an “if” statement and we are ready to roll.
For the purposes of this simple AJAX tutorial, when my .aspx page loads, I am going to request data from a mythical web service (could be Amazon, Ebay, or any number of others), and present it in an asynchronous manner to the user when it comes in. If the service is slow or if I am querying many web services in this page, the user will not be left waiting for them all to come back with a response. The data will show up as it comes in.
Pieces to the puzzle
The first thing we need is a JavaScript function to call on some kind of event. I have chosen an “onload” event for the page, but it could be on a button click, edit box “blur,” image load or whatever. For the example here, all we need to do is put the following in our HTML page body tag:
<body onload=”AsyncDataRequest(1)”>
When the page loads, the browser will make sure that AsyncDataRequest gets called with a parameter of 1. For the following functions, make sure all the code is in a <script language=”JavaScript”> </script> tag in the <head> section of your .aspx page. Also, put a <span id=”ProductInfo1″> </span> in your page where you want the response data to go.
The data request function simply looks at the page parameter passed in (optional), formats a request url and calls the function that actually makes the Http Request:
function AsyncDataRequest (page)
{
var varProduct;
var prodSpan;
if (1 == page)
{
prodSpan = 'ProductInfo1';
varProduct = 'Product1';
}
url = 'http://www.mysite.com/DataRequest.aspx?Query=' + varProduct;
loadXMLDoc (url, processRequest, prodSpan);
}
We pass in a “page” parameter so we can more easily branch our logic based on what object is making the request. Here, for page “1″ we specify the name of a <span> tag (”ProductInfo1″) that will be filled in with our data later on and a product tag (”Product1″) that lets us return more specific information from our query.
We simply formulate the URL with the desired parameters and call another JavaScript function “loadXMLDoc.” That function looks like this:
function loadXMLDoc (url, rsFunc, prodSpan)
{
var reqHTTP;
if (window.XMLHttpRequest)
{
reqHTTP = new XMLHttpRequest();
reqHTTP.onreadystatechange = function()
{
rsFunc(reqHTTP, prodSpan);
};
reqHTTP.open("GET", url, true);
reqHTTP.send(null);
}
else if (window.ActiveXObject)
{
reqHTTP = new ActiveXObject("Microsoft.XMLHTTP");
if (reqHTTP)
{
reqHTTP.onreadystatechange = function()
{
rsFunc(reqHTTP, prodSpan);
};
reqHTTP.Open("GET", url, true);
reqHTTP.send();
}
}
}
This function tests for the existence of the XMLHttpRequest object and makes our asynchronous request for data.
Notice how we have to branch our XMLHttpRequest creation with the if/else if so both IE and Firefox are happy. With Firefox, XMLHttpRequest is a built-in object, but with IE, it is an ActiveXObject. Such is life; just accept it and go on.
The interesting thing here is the assigning of the “onreadystatechange” event of the request object to the function we want to be called when the event fires. In case you haven’t seen it before, the onreadystatechange = function () syntax allows us to define what is known in JavaScript as an “anonymous function.” The cool thing is that we can pass parameters to our callback function, and the script code will take care of preserving those parameters for the callback, even though it occurs later.
Note that “rsFunc” is the parameter we passed in to loadXMLDoc, which we called “processRequest.” That is the function that will be called when the onreadystatechange event of the request fires (basically just when the request gets more data or an error condition). More on that in a second.
The only things left to do here are call “Open” with the URL and “send.”
What does “processRequest” look like? I was hoping you would ask:
function processRequest(reqHTTP, prodSpan)
{
if (reqHTTP.readyState == 4)
{
if (reqHTTP.status == 200)
{
response = reqHTTP.responseText;
document.getElementById(prodSpan).innerHTML = response;
}
}
}
This is simple, boiler-plate code that looks for hardcoded numbers in the response. The readyState of the request has to
be 4 and the status has to be 200. Don’t worry about it, just accept it. Only under those conditions will the request give you good data.
Notice that we passed the request object that we created in loadXMLDoc to this function along with the <span> id originally specified in AsyncDataRequest.
Here, we get the response text from the request object, get the element of the document specified by id (prodSpan) and set its innerHTML to the response text. Voila. The text magically appears in the browser in the place where the <span> tag is. Very cool.
Last piece to the puzzle — data!
So what does the code in DataRequest.aspx look like? That’s mostly up to you. That file does the dirty work of retrieving data from a database, 3rd party web service, validating user input against business rules, etc., etc. Here’s a sample of what it might look like:
String strQueryString = Request.QueryString["Query"];
switch (strQueryString)
{
case "Product1":
Response.Write(MyObject.GetAmazonData("Books");
break;
//Other product feeds responses here
default:
break;
}
Here we are just branching our logic based on the Request string sent in the URL we formatted in the AsyncDataRequest function. Feel free to substitute whatever Request QueryStrings suit your needs.
In the GetAmazonData function you would request your data from the appropriate web service, format it (HTML would be desired here) and write it to the Response stream. Every thing else is automatic. Awesome. You have to supply the logic in MyObject, however. :)
It’s OK for the GetAmazonData function to block for as long as it needs to, because the user is no longer waiting for the page to load. This is the sweet part. Here you could also do secret calculations or password validation, etc.
If you have done everything correctly, whatever HTML you put in Response.Write will show up in the ProductInfo1 <span> tag.
This should be a complete example that you can slice and dice to fit your own needs. If not, please post and let me know. Also, if you have found this helpful, please post your experience for others to read.
As you can see, this could easily be adapted to use in a php environment. The only thing that would be different is the trivial differences in syntax for the DataRequest page.
As an example, this link leads to a games site that has implemented Amazon Web Services as a monetizing tool to present games for sale:
Time Killing Games
Enjoy
midniteblogger