Implementing AJAX Using ASP.NET 1.1
Introduction
You've heard of it. It is the latest buzz term for web programmers these
days. AJAX is an acronym that stands for Asynchronous JavaScript and XML. AJAX
gains its popularity by allowing data on a page to be dynamically updated
without having to make the browser reload the page. I will describe more about
how AJAX works, and then go into some sample code to try out. This term has been made famous by some of Google's latest web apps. At the
top of this list is Google Suggest, which gives you suggestions (go figure) on
what you are searching for as you type based on popularity of the search term.
If you aren't familiar with Google
Suggest, check it out. There is more going on here than just AJAX however. The actual drop down list
is an additional DHTML piece that we will not be covering in this article. Is AJAX a new technology? Yes and no would both be incorrect answers. A
proper answer would be a new application of current technologies, with emphasis
on plurality. This list of technologies includes standard HTML controls,
JavaScript, an XML HTTP component, and XML data structures.
The Steps
The following is an outline of the sequence of events when using AJAX:
Get To It Already!
These steps are great, but without a sample application it is tough to
envision. Being the responsible author that I am, I have of course included a
sample of the steps discussed. I think that it is important to discuss the XML HTTP object to gain a better
understanding of what is going on here. XML HTTP allows code to connect to a
remote location and perform GET and POST requests asynchronously. This means
that we can connect to a remote host, send a request, and continue on with
additional logic. When the remote host returns a response, a function designated
to handle the return event is able to accept the data and make decisions based
on what was received. The data passed to and from the remote host does not have
to be in an XML format. XML is simply a well-formatted string. I have found on
multiple occassions that passing a string that is not in an XML format is most
appropriate for the given task. The XML HTTP object will not be compatible on
all browsers or operating systems. Being that this is a client side function the
client machine is responsible for the implementation as opposed to the server. I have been utilizing this object since ASP 3.0 for making remote calls from
a web page. Imagine the power here. Data and processes are accessed on disparate
locations without the client ever having to leave the comfort of the domain or
page that he/she is on.
The JavaScript
The JavaScript is the real meat and potatoes in AJAX. It handles the change
detection, data request and receipt, and placing the data on the page. Be sure to update the requestURL variable with the path that you will be
accessing the aspx file from. The following is the JavaScript code used:<script>
var xmlHttp;
var requestURL = 'http://localhost/misctest/getusernames.aspx?q=';
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){
if (strName.length > 0){
//Append
the name to search for to the requestURL
var url
= requestURL + strName;
//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);
}
else {
//Textbox
blanked out, clear the results
document.getElementById('nameList').innerHTML
= '';
}
}
//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;
//Populate
the innerHTML of the div with the results
document.getElementById('nameList').innerHTML
= str;
}
}
// 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;
}
function UseValue(strVal){
document.frmStuff.txtName.value
= strVal;
}
</script>
The Client Page (HTML)
The client page, excluding the JavaScript, is about as basic as it gets. A
simple form with an onKeyUp event in a text box is all that is really required.
I included a DIV tag to display the resulting data. The HTML has been
provided:<html>
<head>
<title>Ian Suttle's AJAX Sample</title>
<style>
body, input {font-family: arial;
font-size: 12px;}
</style>
<!-- Insert JavaScript Here -->
</head>
<body>
<form name="frmStuff"
id="Form1">
<table border="0"
cellpadding="4" cellspacing="0" id="Table2">
<tr>
<td
width="100">Name:</td>
<td><input
type="text" name="txtName" id="txtName"
autocomplete="off" onkeyup="show_data(this.value);"></td>
</tr>
<tr>
<td
width="100" valign="top">Suggestions:</td>
<td>
<div
id="nameList"></div>
</td>
</tr>
</table>
</form>
</body>
</html>
The Remote Page
When a request is made from the JavaScript, it makes contact with the
"remote page." A query string variable, "q", is included
representing the data that was keyed by the user. I am going to construct an XML
string, only including those elements that are valid based on the search term.
To relieve the client side script from doing any formatting, I have applied an
XSL transformation on the XML data. Formatting the XML on the server side is a
much better solution than formatting within the JavaScript on the client side. A
major point to recognize is that certain browsers will not support XML and XSL
objects. Assuming you want your data to always be formatted the same, stick with
the server side logic. Create a page called GetUsernames.aspx. Be sure to remove ALL HTML from the
page except the required @Page line. The code-behind will create the output to
display on the page. Add the following code to the code-behind file:using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
namespace MiscTest
{
/// <summary>
/// Summary description for GetUsernames.
/// </summary>
public class GetUsernames : System.Web.UI.Page
{
private void Page_Load(object
sender, System.EventArgs e)
{
GetUsernameList();
}
#region Web Form Designer
generated code
override protected void
OnInit(EventArgs e)
{
//
//
CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}
/// <summary>
/// Required method for Designer
support - do not modify
/// the contents of this method
with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Load
+= new System.EventHandler(this.Page_Load);
}
#endregion
private void GetUsernameList()
{
//Get
the request query
string
strQuery = Request["q"].ToString();
//Create
the XML-like string to be sent back to the request
string
strXmlNames = "";
//An
arbitrary array of names that will be written to an XML Document.
string[]
arrStrNames = new string[5]{"Ian Suttle", "John Doe",
"Alex Wright", "Albert Einstein", "Sierra Tracy"};
//Loop
through the names, creating a psuedo XML element for each
foreach(string
strName in arrStrNames)
{
//If
the request matches the beginning of a name, then add it to the string
//
otherwise it shouldn't be a valid match
if
(strName.ToLower().Substring(0, strQuery.Length) == strQuery.ToLower())
strXmlNames
+= "<user><name>" + strName +
"</name></user>";
}
//Prepend
and append the parent element
strXmlNames
= "<?xml version=\"1.0\" ?><users>" +
strXmlNames + "</users>";
//Create
an XmlDocument object to store the XML string that we created
XmlDocument
xDoc = new XmlDocument();
xDoc.LoadXml(strXmlNames);
//Create
a navigator object to use in the XSL transformation
XPathNavigator
xPathNav = xDoc.CreateNavigator();
//Create
the XSLTransform object
XslTransform
xslt = new XslTransform();
xslt.Load(Server.MapPath("Names.xslt"));
//Do the
transformation and send the results out to the Response object's output stream
xslt.Transform(xPathNav,
null, Response.OutputStream);
}
}
}
The XSL Stylesheet
The XSL document is used to format the XML data to a defined presentation.
The code to do the transformation is included here, although great detail on how
this works is not the topic of this article. Create a new XSL document called
Names.xslt and paste the following code into it:<?xml version="1.0"
encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:for-each
select="users/user">
<xsl:value-of
select="name" /><br />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Conclusion
So once again, AJAX is nothing more than an application of technologies that
have been around for a number of years. ASP.NET isn't the wizard behind this
curtain. There is nothing here that can't be done in ASP Classic and JavaScript.
Not that given a choice one would revert to ASP Classic :). Additionally,
ASP.NET 2.0 will have a completely different approach to making remote calls
from a page. The possible implications of AJAX are very impressive. Updating notices,
checking email, monitoring processes, etc... The limits of application are
virtually up to the imagination of the developer.