Article Author: Keith Harvey
Introduction
Note. This article was updated on 12 July 2005 to improve the processing of the ASP.NET cache in the sample code.
Creating interactive and responsive user interfaces with ASP.NET 1.x can be a challenge, especially when it comes to displaying dynamic data. However this whole issue of displaying such dynamic data took an unexpected twist recently when Google released Google maps, http://maps.google.com, which used a combination of JavaScript and the XmlHttp object to produce an unusually interactive and responsive web site, which quickly aroused the intereste of the developer community. The technology combination quickly became known as AJAX and seems to have become quickly recognized as one of the standard techniques for presenting dynamic content (despite having actually been around for quite a long time, without, apparently, that many developers noticing – until Google used it!). Unfortunately, support for AJAX within ASP.NET is currently quite limited, although this is likely to improve in ASP.NET 2.0, notably with Microsoft’s announcement of the forthcoming release of Atlas. One possible route for developers wishing to use AJAX with ASP.NET 1.x is to use Michael Schwarz’s AJAX.NET library, which provides a generic library wrapper to make AJAX-based development relatively easy, though at the cost of hiding some of what is actually going on.
In this article I’ll show you how to build AJAX functionality into an ASP.NET web page from first principles, without using any additional components beyond what comes out of the box in ASP.NET 1.x. You’ll see that the process is relatively simple and gives you a clear idea of how AJAX actually works and what is going on under the hood. The specific example I’ll take is of providing suggestions as a user types in a string into a text box, and for this I’ll take the scenario of an administrator searching for a user on a system, hence the suggestions returned will be possible usernames that might match what the administrator has typed in so far. Because the purpose of the article is to demonstrate AJAX, I’m not going to worry about how the list is retrieved “ in fact the sample application will take the simplest possible approach have the list hard-coded into the C# source code (more realistically the list would probably originate in some database or Active Directory).
I’ll start by briefly reviewing AJAX concepts, for the benefit of anyone still unfamiliar with AJAX, and then I’ll present the sample code.
System Requirements
To run the sample code associated with this article, you simply need a web server running ASP.NET 1.x and IE or Firefox as a web client.
Installing and Compiling the Sample Code
To install the sample code, you should download and unzip the zip file, and create an IIS virtual directory called AJAX which points to the location to which you extracted the files. The sample should then open and compile in VS.NET 2003. The main files of interest are:
- Serarch.aspx “ the main page in the file. You should set the start page to this file.
- Server.aspx – the page that responds to XMLHTTP calls.
- AJAXFunctions.js “ contains the client-side files that implement AJAX features.
Understanding AJAX
Let’s show how AJAX works by examining an example scenario “ in fact, the one that I’ll demonstrate in the later sample: search functionality.
Example: Searching
In this scenario a user types a keyword into a textbox and clicks a search button. The page is posted back to the server, where a search is executed against a database and the results are rendered into HTML and sent back to the browser, as shown in Figure 1. Each separate search is a complete page roundtrip and the user has to sit and wait for the page to be rebuilt each time.

Figure 1. The Traditional Page Roundtrip Model
There are some glimmers of light. With the advent of JavaScript, Cascading Style Sheets (CSS) and Dynamic HTML (DHTML), professional web developers and designers have gained many options for offering richer user interfaces. All of the major third-party web control publishers use these technologies to build interactive menus, grids, charts and many other useful tools. While this improves the look and feel of the user-interface, the overall problem of page round trips still applies every time the user needs to view more data from the server.
AJAX can solve these problems. AJAX in itself isn’t a new technology, but it is a blending of existing technologies that allow a browser’s client-side (JavaScript) to make requests and receive data from the server asynchronously using the XmlHttp API over HTTP without the need for complete page roundtrips. The data can be returned from the server in almost any conceivable format, including XML, HTML and even binary data. The model is shown in Figure 2.

Figure 2. The AJAX Model
Now, an ASP.NET developer can leverage AJAX, using Internet Explorer, or Mozilla FireFox straight away without the need to install components on the user’s system.
While AJAX could be used for many purposes (use your imagination!), its true strength lies in enabling professional ASP.NET developers to build interactive and responsive user interfaces. AJAX is indeed incredible!
The Elements of AJAX
The high-level concept behind AJAX is pretty straight forward. The web browser makes client-side calls to a library of JavaScript functions, which then send asynchronous requests to the web server using the XmlHttp API . The server responds by carrying out any appropriate processing after which it sends data back to the client, where it is processed and rendered, by client-side JavaScript. The beauty of AJAX is that the XmlHttp API handles all of the asynchronous operations for you, allowing you to concentrate on your application’s functionality instead of low level details.
The Client-side Library
The heart of AJAX is a library of client-side JavaScript functions. The library is responsible for accepting calls from the user interface, sending requests to the server, and then processing and rendering the results.
Since AJAX isn’t a distinct technology, there is quite a bit of flexibility in how a library could be designed and developed. However we can define two primary pieces that make up the library and are shown in Figure 3.

Figure 3. The elements of an AJAX library
The first is the User Interface Functions . These are functions that process input from the user and render data that has been received from the Server Request and Callback Functions to the user interface. Rendering is typically done by using Dynamic HTML (DHTML), Cascading Style Sheets (CSS) and the browser’s Document Object Model (DOM).
The second is Server Request and Callback Functions . These are functions that process calls from the User Interface Functions which in turn uses the XmlHttp API to send requests to the server. Since XmlHttp communicates asynchronously, there needs to be functions to handle the responses from the server. These "callback" functions will process the data returned from the server and then make calls to the User Interface Functions so that they can be processed and rendered to the user interface.
XmlHttp
The API that allows the AJAX library to communicate with the server is provided through a component called XmlHttp. Both Internet Explorer and Mozilla FireFox have XmlHttp support. . Internet Explorer accesses it through a separate ActiveX component which is installed by default while FireFox doesn’t require any ActiveX component but rather has XMLHTTP support integrated directly into the browser. Regardless, you can use XmlHttp with these browsers without worrying about installing components on a user’s PC.
XmlHttp can communicate with a server asynchronously or synchronously via the HTTP protocol. AJAX uses asynchronous communications. This allows an ASP.NET developer to create and send a request to the server, designating a JavaScript call-back function to accept and process data that is returned. While synchronous calls could be used, you run the risk of having your code hang if the server or the network is having problems.
A common concern is that this model isn’t much different from normal page roundtrips. These are asynchronous calls and the user has to wait for the results. This is true, but the key difference with XmlHttp is that the requests to the server and the data to be returned are meant to be small and lightweight. The goal is to keep processing time on the server as quick as possible and return the absolute smallest amount of data needed. With this in mind, XmlHttp calls can be sent in rapid fashion, with the user seeing results virtually in real-time. A user’s perception is indeed reality!
The Server
With AJAX you can communicate with any server that can accept and process HTTP requests. This provides a lot of flexibility in that you can use quite an array of server-side technologies (e.g. ASPX, ASP, web services, etc.). In the context of ASP.NET development it is quite easy to send requests and receive responses from specially designed, lightweight ASPX pages. These pages are designed with no user interface and are used to receive specific requests and return small pieces of data. While there are higher performance alternatives to using ASPX – such as web services – I have found that properly designed ASPX pages are easy to implement and perform well for most applications.
Seeing is Believing
Is anyone really using this technology? Does it truly work? The answer to both of those questions is an emphatic yes. One of the pioneering users of AJAX is Google. Take a look at Google’s Suggest (http://www.google.com/webhp?complete=1) , Maps (http://maps.google.com) and Gmail (http://gmail.google.com). All of these services use AJAX extensively. The Google Suggest Beta will give you instant gratification, showing a dynamic dropdown of suggested search terms along with the number of results they return as you type in the search box.
Using AJAX to Dynamically Search a List of Users
As a professional ASP.NET developer you have most likely faced the issue of having to provide search or lookup functionality in one of your applications. An example would be an Administrator needing to search a directory of users, locate the user and then edit their information. While there are many ways to accomplish this task, wouldn’t it be great if you could provide a textbox that would dynamically search the user list and display a dropdown box with a list of users as the Administrator typed? Figure 4 shows the sample in action “ as you can see it’s quite similar to Google suggest, although for simplicity I’ve used a panel rather than a drop-down list to display the suggestions.

Figure 4. Sample AJAX application in action
This is definitely a perfect example for the use of AJAX. Let’s build a small sample ASP.NET application that does just that, using AJAX to dynamically query a list of users stored on the server.
The Pieces of Our Application
To make our AJAX application work, you’ll need to build the following:
- Search Page “ This is the page that the Administrator will use to search against a list of users stored on the server.
- AJAX Library “ This will be the User Interface Functions and Server Request and Callback Functions that are needed to accept the text typed by the Administrator, send the search requests to the server and render the returned data to the search page.
- Server Search Page “ This is the page that will accept search requests from the AJAX Library, search against the user list on the server and return the results back to the AJAX Library.
Let’s get started!
Building the Search Page
The key to learning any new technology is to keep things as simple as possible. So, for our Search page, you’ll use three controls.
- Textbox “ The Administrator will use this to type in his/her user search
- Panel “ This will be the floating drop down box that will contain the results from the server
- Label “ This will display the user that is finally selected from the search
Figure 5 shows what the page will look like in the Visual Studio .NET Designer.

Figure 5. The page, as seen in Visual Studio designer
Before proceeding it is important to note that ASP.NET by default doesn’t support the FireFox browser. Because it doesn’t detect FireFox, it treats it as a down-level browser, rendering web controls in a way that breaks functionality. This can be solved by inserting a <browserCaps> section into your Web.config file that ASP.NET will use to detect FireFox.
<browserCaps>
<!— mozilla & netscape —>
<case match="Gecko/[-d]+">
browser=Netscape
frames=true
tables=true
cookies=true
javascript=true
javaapplets=true
ecmascriptversion=1.5
w3cdomversion=1.0
css1=true
css2=true
xml=true
tagwriter=System.Web.UI.HtmlTextWriter
<case match="rv:1.0[^.](?‘letters’w*)">
version=6.0
majorversion=6
minorversion=0
<case match="^b" with="${letters}">
beta=true
</case>
</case>
<case match="rv:1(.d+)(.d)?(?‘letters’w*)">
version=7.0
majorversion=7
minorversion=0
<case match="^b" with="${letters}">
beta=true
</case>
</case>
</case>
</browserCaps>
You can find more details about this issue in Gert Gerardi’s ASP Today Firefox series, at http://www.asptoday.com/Content.aspx?id=2339.
In order to capture the search text as the Administrator types, you’ll need a DHTML event that can be attached to the textbox to detect when a key has been pressed while focus is in the textbox. The onkeypress() function will handle this perfectly. Adding this event can easily be done in the HTML view in Visual Studio. This event will need a function to call. In this case you should have it call the CaptureSearchText() function in your AJAX library. Here is what this will look like in the HTML view:
<asp:textbox id="SearchTextBox" style="Z-INDEX: 1; LEFT: 8px; POSITION: absolute; TOP: 32px" runat="server" width="248px" onkeyup="CaptureSearchText()" />
The panel control will be the "magic" floating box that automatically pops up as soon as text is entered into the textbox. When the page loads the textbox will be empty so the panel needs to be invisible. Setting the panel’s visibility style property in the HTML will take care of that. Be careful of the choice of property here: If you set the Visible property of the panel in the designer, when the page is rendered at runtime the panel object won’t be there. However using the visibility style property will ensure that the object will be there for you to manipulate.
<asp:panel id="ResultsPanel" style="Z-INDEX: 3; LEFT: 8px; POSITION: absolute; TOP: 96px; VISIBILITY:hidden;" runat="server" width="360px" height="216px" backcolor="#FFFFC0" />
In Figure 5 the panel is located well below the textbox and label controls. At runtime you should change its location so that it appears just below the textbox. That’s the beauty of DHTML and the grid layout in Visual Studio’s designer. But, in order for the panel to display on top of the label control you’ll need to adjust its z-index attribute. In DHTML, controls can overlap each other and the z-index attribute is what controls the order of the controls. The higher the z-index , the higher the display priority.

Figure 6. The z-indexes
In this case you’re going to set the z-index attribute of the panel control to 3. Here is what it looks like in the HTML view.
<asp:panel id="ResultsPanel" style="Z-INDEX: 3; LEFT: 8px; POSITION: absolute; TOP: 96px; VISIBILITY:hidden;" runat="server" width="360px" height="216px" backcolor="#FFFFC0" />
The Search page is almost complete. The last thing that needs to be done is to add a reference to the AJAX library in the <head> block of the HTML. Often, developers will include client-side JavaScript code directly in the HTML of their pages. If your AJAX library is simple and only used in one place then this is definitely an option. I have found that keeping JavaScript code in a separate file keeps my pages clean and gives me ample opportunities for re-use. Here is what the reference to our AJAX library looks like in the HTML.
<script language="javascript" src="AJAXFunctions.js"></script>
With the Search page complete, let’s build the AJAX library!
Building the AJAX Library
This is the heart of the application. Previously I talked about the library conceptually having User Interface Functions and Server Request and Callback Functions, as you saw in Figure 3. Let’s take a look at each one.
User Interface Functions
- CaptureSearchText() “ This is the function that is called from the onkeypress event that you added to the textbox control. This function will get the text from the textbox and then pass it to the SendSearchRequest function so that a request can be made to the server.
- DisplaySearchResults(searchResults) “ This function will accept the formatted search results from the ReceiveSearchResults function and will display them in the panel control of the Search page.
- DisplaySelectedResult(selectedResultText) “ This function will accept the final selected search result from a hyperlink in the panel control and will display it in the textbox and the label control. This function will also hide the panel.
Server Request and Callback Functions
- SendSearchRequest(searchText) “ This function will accept the search text from the CaptureSearchText function and send it as a request to the server using the XmlHttp API.
- ReceiveSearchResults() “ This function will serve as the callback for the SendSearchRequest function. This function will asynchronously retrieve the results from the server and will prepare the data to be displayed by the DisplaySearchResults function.
The Client-Side Code
Let’s take a look at the code for the functions in the order they would be called.
CaptureSearchText()
This is the simplest function in our library. It is going to get a reference to the textbox control and then extract the contents. Here is what it looks like.
function CaptureSearchText()
{ // Get a reference to the SearchTextBox control and // extract the contents into a variable var searchTextBox = document.getByElementId("SearchTextBox"); var searchText = searchTextBox.value.toLowerCase(); // Call the SendSearchRequest function SendSearchRequest(searchText);
}
SendSearchRequest(searchText)
This is where the heart of AJAX “ XmlHttp “ is used to communicate with the server. As we covered previously, XmlHttp is asynchronous, so we will use this function to make our request and a separate function to handle the result.
function SendSearchRequest(searchText)
{ // Create a new XmlHttp object if(browser "IE") { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } else if(browser "FF") { xmlHttp = new XMLHttpRequest(); } // Define the request url and encode the search text var requestUrl = "Server.aspx?searchtext=" + encodeURIComponent(searchText); // Tell XmlHttp that our request is asynchronous var isAsyncRequest = true; // If the object is successfully created then if(xmlHttp) { // Set the callback function xmlHttp.onreadystatechange = ReceiveSearchResults; // Send the request xmlHttp.open("GET", requestUrl, isAsyncRequest); xmlHttp.send(null); }
}
ReceiveSearchResults()
This is the callback function that receives the results from the server. This function will check whether the response from the server is complete and OK. If everything is fine, it will then call our display function with the results returned from the server.
function ReceiveSearchResults()
{ // Make sure the response is complete if(xmlHttp.readyState 4) { // Make sure the return status from the server is OK if(xmlHttp.status 200) { // Get the results from the server and call // the DisplaySearchResults function DisplaySearchResults(xmlHttp.responseText); } else { alert("There was a problem retrieving data from the server."); } }
}
DisplaySearchResults(searchResults)
Since we are keeping things simple, the server is going to generate the HTML that we are going to display in the panel control. When the results are successfully received by the ReceiveSearchResults function, this function will write the HTML to the panel control. When the Search page was loaded, we had set the panel control to be hidden. Now that we are returning results, we need to make it visible and position it just below the textbox to make our "magic" complete.
function DisplaySearchResults(searchResults)
{ // Get a reference to the ResultsPanel control and // render the results from the server var resultsPanel = document.getElementById("ResultsPanel"); resultsPanel.innerHTML = searchResults; if(searchResults != "") { // Make sure that the panel is in the proper position // and that it is visible resultsPanel.style.top = "55px"; resultsPanel.style.visibility = "visible"; } else { // The server returned no results so hide the panel resultsPanel.style.visibility = "hidden"; }
}
DisplaySelectedResult(selectedResultText)
Finally, the user can click on a name displayed in the panel control. This function is called from a hyperlink associated with each individual item in the results panel. It will hide the panel control and set the contents of the textbox and label with the name of the selected user.
function DisplaySelectedResult(selectedResultText)
{ // Get references to our controls var searchTextBox = document.getElementById("SearchTextBox"); var resultLabel = document.getElementById("ResultLabel"); var resultsPanel = document.getElementById("ResultsPanel"); // Set the contents of the textbox and label to our selected result searchTextBox.value = selectedResultText; resultLabel.innerHTML = "You selected: " + selectedResultText; // Hide the results panel resultsPanel.style.visibility = "hidden";
}
Building the AJAX library was pretty straight forward. Our example is simple, but hopefully you can see the incredible possibilities AJAX offers! Let’s take a look at the final piece of our application.
Building the Server Page
On the server, we will need to process the requests from the AJAX library and return the results. This can be easily done with an ASPX page. An important thing to note is that you don’t need to create any special code in your ASPX page in order to process and send responses to requests made by an AJAX library via XmlHttp!
This ASPX (Server.aspx) page will have no user interface (no HTML) and will do all its work in the code-behind. It will use a single method that will receive the incoming data from the request and will then query a cached array of user names which will return the result as a string of formatted HTML that will ultimately be displayed in the panel control on the Search page.
Since there is no need for a user-interface, the only markup needed in the Search.aspx page is the page declaration:
<%@ Page language="c#" Codebehind="Server.aspx.cs" AutoEventWireup="false" Inherits="ASPToday.AJAX.Server" %>
Returning the Formatted UserList
The processing of the AJAX requests starts in the Page_Load event of Search.aspx .
private void Page_Load(object sender, System.EventArgs e)
{ if(!IsPostBack && Request["searchtext"] != null) { // Get the search text from the request string searchText = Request["searchtext"]; // Make sure that the search text is not empty if(searchText.Length > 0) { SearchUsers(searchText); } else { Response.Clear(); Response.End(); } } else { Response.Clear(); Response.End(); }
}
First the method retrieves the search text passed as a HTTP Request item. If the search text is blank or the request item does not exist then we will simply clear and end the request. Otherwise the search text will be passed to the SearchUsers() method where we will connect and search the user name list for matches.
Retrieving Data from the Cache
The SearchUsers() method will load a string array from the ASP.NET cache. It will then iterate through the array looking for matches using the .NET IndexOf() function. The search text that was passed in is converted to lower case as is the user name from the array. If the search text is present anywhere in the user name, then a match is registered and an HTML table row is created for the results. The code for the method looks like this:
private void SearchUsers(string searchText)
{ string[] users = GetUserListFromCache(); StringBuilder searchResults = new StringBuilder(); StringBuilder finalResult = new StringBuilder(); searchText = searchText.ToLower(); int resultsFound = 0; int maximumResults = Convert.ToInt32(ConfigurationSettings.AppSettings["MaximumResults"]); foreach(string user in users) { if(user.ToLower().IndexOf(searchText) != -1) { resultsFound++; searchResults.Append("<tr><td><a href="#" onclick=‘DisplaySelectedResult("" + user + "")’>" + user + "</a></td></tr>"); if(resultsFound maximumResults) { break; } } } if(resultsFound > 0) { finalResult.Append("<table cellpadding="2" cellspacing="0" border="0" width="100%">"); finalResult.Append("<tr><td>Users found: " + resultsFound.ToString() + "</td></tr>"); finalResult.Append(searchResults.ToString()); finalResult.Append("</table>"); Response.Clear(); Response.Write(finalResult.ToString()); Response.End(); } }
Once the search is complete, if there were any matches registered, the final pieces of the HTML table are assembled and the response is returned back to the ReceiveSearchResults() function in the AJAX library. Ideally, you would use the server to only receive and send data. That way you could write multiple AJAX libraries that can use the same server services.
You'll notice the very first thing that SearchUsers() does is call a method, GetUserListFromCache() . The fact that the data is taken from the cache is pretty important " given the number of times this page is likely to be invoked (every time the user presses a key), performance is going to be very important. For similar reasons, you'll probably find that very often when you write Ajax-enabled applications, you'll want to make extensive use of the ASP.NET cache. Here's GetUserListFromCache() , along with a couple of important constants.
const int cacheLifeTimeMinutes = 10;
const string userListCacheName = "UserList";
public string [] GetUserListFromCache()
{
string [] list = Cache[userListCacheName] as string[];
if (list null)
{
list = GetTheUsers();
Cache.Insert(userListCacheName, (object)list, null,
DateTime.Now.AddMinutes(cacheLifeTimeMinutes), TimeSpan.Zero);
}
return list;
}
As you can see this method attempts to retrieve the list of users from the cache, but if it’s not available there, it’ll repopulate the cache from the original data source, using the method, GetTheUsers() , and indicating the cache should retain the value for 10 minutes (which for this kind of application seems a reasonable length of time). In this case, to keep the sample simple, I’ve implemented GetTheUsers() to retrieve hard-coded results, but more realistically you’d probably implement the method to look up a database or Active Directory.
The Final Step
Back in the AJAX library if we have received search results from the server, the resulting HTML is inserted into the panel control and its location and visibility are set. In this example the server also rendered an anchor tag that will call the DisplaySelectedResult() function in the AJAX library. This function will hide the results panel and will replace the textbox and label controls with the user name that was selected.
Conclusion
AJAX is a very powerful and flexible combination of technologies that allow ASP.NET developers to create responsive, interactive user interfaces that communicate with the server in real-time. Using AJAX in an ASP.NET application is easy to do and can be as simple or as complex as needed. In this article I’ve worked through a sample AJAX-enabled page that dynamically populates a list of suggestions as the user types a string into a textbox.
Using the information and simple example in this article it is my hope that you will experiment and successfully use AJAX in your ASP.NET applications.

