Ajax
Ajax
Ajax
Introduction
Since the start of Web programming, numerous tradeoffs have existed
between Web applications and desktop applications. For example, it has been
generally accepted that Web applications don't provide the same type of rich user
interface as desktop applications. On the flip side, Web applications are platform
independent and provide an easier development mechanism. One area that's been a
continuous battleground for Web developers has been the seemingly simple task of
providing more responsive applications.
Traditionally, a response to a user's input could only be retrieved by
submitting a new request to the Web server. In some cases, developers could load all
responses on the client (using JavaScript) and provide a better user experience. A
common example of this technique is to dynamically load a list of states or
provinces, based on a selected country. Unfortunately, in many cases, neither posting
back nor loading everything into JavaScript felt correct. Either posting back created
too much of a UI disconnect, or an unmanageable amount of data was required on
the client (which often resulted in less-than-readable JavaScript). AJAX provides a
new in-between alternative, capable of leveraging the server-based application while
maintaining a responsive and slick feel.
What Is AJAX?
AJAX, short for Asynchronous JavaScript And XML, isn't a technology but
rather a grouping of technologies. AJAX uses a communication technology (typically
SOAP and XML) to send and receive an asynchronous request/response to the server,
and then leverages presentation technologies (JavaScript, DOM, HTML, and CSS) to
process the response. Applications using AJAX are legitimate today, because most
browsers support the necessary technology. For a more detailed definition of AJAX,
visit the AJAX Wikipedia entry.
What does AJAX really mean? It lets you execute a server-side method
through a JavaScript call, without requiring a browser refresh. Think of it as a mini
request/response that happens behind the scenes from the user. If you still aren't
clear what AJAX is, take a look at two popular examples from Google: Google
Suggests and Google Maps. If you are new to AJAX, the responsiveness of those two
applications should make your skin tingle slightly.
AJAX Hands-On
The remainder of this article will mostly be devoted to three meaningful
examples that utilize the power of AJAX using Ajax.NET. The guide will contain code
in both Microsoft C# and Microsoft Visual Basic .NET, sometimes both will be
provided, and sometimes only one or the other. The code to make all this happen is
so easy, that C# developers should be able to easily follow the Visual Basic .NET-only
code, and vice versa! Sample C# and Visual Basic .NET projects are included with
this article for download, and provide working and running code. Before we get to
the examples, a primer on setting up and working with Ajax.NET is necessary.
Ajax.NET
<configuration>
<system.web>
<httpHandlers>
<!-- Register the ajax handler -->
<add verb="POST,GET" path="ajax/*.ashx"
type="Ajax.PageHandlerFactory, Ajax" />
</httpHandlers>
...
...
</system.web>
</configuration>
The beginning of this article briefly discussed the two traditional approaches
used for linking one DropDownList to another. Either the page is posted back when
the selected index changes or all the possible data is loaded into JavaScript arrays
and dynamically displayed. Hopefully you can see how AJAX might be used as an
alternative to both of these solutions.
First, let's look at our data interface and drive the example from there. Our
data access layer will expose two methods: the first will retrieve a list of countries
our system supports, while the second will take a country ID and return a list of
states/provinces. Since this is pure data access, we'll just look at the method
signatures.
//C#
public static DataTable GetShippingCountries();
public static DataView GetCountryStates(int countryId);
'VB.NET
Public Shared Function GetShippingCountries() As DataTable
Public Shared Function GetCountryStates(ByVal countryId As Integer) As
DataView
Now, let's flip to the opposite layer and create our simple Web form.
//C#
Ajax.Utility.RegisterTypeForAjax(typeof(Sample));
'VB.NET
Ajax.Utility.RegisterTypeForAjax(GetType(Sample))
We're almost done; all that's left is to call the GetStates method from
JavaScript and handle the response. We logically want to call GetStates when the
user selects a new item from the list of countries. To do so, we'll hook into the
JavaScript onChange event. Our Web form code thus changes slightly.
After a bit of error checking, the preceding JavaScript gets the states drop-down list,
loops through the response's value, and dynamically adds options to the drop-down
list. The code is clean, straightforward, and eerily similar to C# and Visual Basic
.NET. Personally, as a developer who's created JavaScript arrays based on server-side
variables and linked them together, I still have a hard time believing it actually
works.
There is one major issue that might not be obvious. Since the DropDownList was
dynamically created in JavaScript, its items aren't part of the ViewState and won't
be maintained. That means that our button's OnClick event handler needs to do
some extra work.
'VB.NET
Private Sub submit_Click(sender As Object, e As EventArgs)
Dim selectedStateId As String = Request.Form(states.UniqueID)
'should do some user validation...
states.DataSource =
DAL.GetCountryStates(Convert.ToInt32(countries.SelectedIndex))
states.DataTextField = "State"
states.DataValueField = "Id"
states.DataBind()
states.SelectedIndex =
states.Items.IndexOf(states.Items.FindByValue(selectedStateId))
End Sub
First, we can't use the states.SelectedValue property and must use Request.Form.
Second, if we want to redisplay the list to the user, we need to bind the states
DropDownList, thankfully reusing the same data access method. Finally, the
selected value has to be programmatically set.
For our next example, we'll take a more complete feature and improve it with
AJAX. This example will be of a simple document management system. Like any
decent document management system, we have to provide concurrency
management. That is, we need a way of handling two users trying to edit the same
document. We'll do so by creating some type of locking mechanism that prevents
one user from editing a document already being edited. We'll use AJAX to make the
user's experience with our locking mechanism more pleasant. First, we'll create a
queue of documents the user tried to edit but couldn't (because it was already being
edited), and automatically notify him or her when they become available. Second,
we'll make sure to unlock a document if the user closes his or her browser or
navigates away. This last feature helps ensure that documents don't stay forever
locked. For the purpose of this guide, we'll skip the functionality not related
specifically to the AJAX implementation; however, the downloadable project contains
everything.
First, when a user tries to edit a document, we'll try to acquire an exclusive
lock on it and, failing that, we'll add the document to the user's queue and send him
or her back to the main page. There's nothing specific to AJAX here, but we'll look at
the code in order to give the example the necessary context. In the OnLoad event of
the Page used for editing, the following is added.
//C#
if (!Page.IsPostBack)
if (!Locker.AcquireLock(document))
The key line is where the document is added to the current user's queue,
which adds it to the session. Next, we'll create a user control, which can be placed on
any page, used to notify the user when a queued document has become available.
This user control will contain a single AJAX method, along with the code necessary to
register the class with AJAX.
All that's needed now is some JavaScript to make the request and handle the
response. We'll place the released document information, if any, inside a table that
we'll dynamically build, based on the response. To do so we'll start off with our
HTML.
<div id="notifyBox" style="display:none;">
<b>The following queued documents can now be edited</b>
<table cellpadding="5" cellspacing="0" border="0"
style="border:1px solid #EEE;" id="notifyTable">
</table>
</div>
We use the DIV tag to hide everything when no documents are available (or maybe
none are queued for the user), and the TABLE tag to display the results. We'll use a
polling system to see if any queued documents are available. Basically, this means
we'll keep calling the server-side method, with a delay, and display the results. The
first call will simply occur when the page loads, and subsequent calls will be timed to
happen every X seconds.
All that's left is to handle the response. This is similar to the code from the
previous example. First, check for any errors, get the response, loop through the
available documents, and dynamically build our HTML, in this case adding rows and
columns to our table.
function PollQueue_CallBack(response) { var notifyBox =
document.getElementById("notifyBox"); var notifyTable =
document.getElementById("notifyTable"); //if we couldn't find our table notification box
if (notifyBox == null || notifyTable == null) { return; } //if the server-side code threw an
exception if (response.error != null) { notifyBox.style.display = "none";
alert(response.error); //we should probably do better than this return; } var documents =
response.value; //if the response wasn't what we expected if (documents == null ||
typeof(documents) != "object") { notifyBox.style.display = "none"; return; } for (var i =
0; i < notifyTable.rows.length; ++i) { notifyTable.deleteRow(i); } for(var i = 0; i <
documents.length; ++i) { var row = notifyTable.insertRow(0); row.className = "Row" +
i%2; var cell = row.insertCell(0); cell.innerHTML = documents[i].Title; cell =
row.insertCell(1); var date = documents[i].Created; cell.innerHTML = date.getDay() + "/"
+ date.getMonth() + "/" + date.getYear(); cell = row.insertCell(2); cell.innerHTML = "<a
href='DocumentEdit.aspx?id=" + documents[i].DocumentId + "'>edit</a>"; }
notifyBox.style.display = "block"; }
The last example we'll look at will be the modification of an existing app. I
heard this idea first proposed by Josh Ledgard as a feature being played with for the
MSDN forums. The goal of it is to try to help users with questions help themselves,
as well as to curb the number of duplicate posts. Basically, when a user goes to ask a
new question in the forum, he or she enters a subject and a question, all too often
not doing a search to see whether the question was already asked and answered.
Enter AJAX. After the user finishes entering the subject (and tabs out of the field),
we'll asynchronously search the forums, based on the subject, and non-obtrusively
present the results to the user. Sometimes the results will be helpful, sometimes not.
To accomplish this, we'll modify the asp.NETPRO Reader's Choice Award for
Best Forum Application, CommunityServer. The downloadable samples doesn't
include the code in this section (or the forums), but you can learn more about
CommunityServer at http://communityserver.org/ and apply the following code
snippets to it.
With CommunityServer installed and Ajax.NET configured (references and
handler added to web.config), we need only make a few changes to get the desired
functionality. First, we'll go to the CreateEditPost.cs file in the
CommunityServerForums project. Think of this as the code-behind for the page
where users go to add a new post. Here we'll add our AJAX-enabled function.
//C# Ajax.Utility.RegisterTypeForAjax(typeof(CreateEditPost));
Before we can jump into JavaScript, we need to make one final server-side change.
Custom classes returned to Ajax.NET, such as the ForumPost contained in the
ArrayList we are returning, must be marked with the Serializable attribute. All we
do is go into the Components/ForumPost.cs file of the
CommunityServerForums project, and add the attribute.
//C# [Serializable] public class ForumPost : Post { ... }
Next, we write the JavaScript Search method so that it calls our server-side Search.
Finally, all that's left is to handle the response. Since the previous example
showed a slightly more elegant way to display results in a table, we'll merely create
some dynamic HTML and stick it into a fictitious DIV.
Will an application that uses AJAX be harder to maintain? The answer largely
depends on how much JavaScript you are already using, and how good you are at
organizing and maintaining it. Many developers feel that JavaScript is harder to
write, test, and debug (not because of JavaScript itself, but because of tool support
and developer knowledge). If you are currently implementing a linked drop-down list
using JavaScript, and switch to AJAX, your code will probably get easier to maintain
(Ajax.NET's support for .NET types and arrays is a big reason for this). However, if
you are going the post-back route, you'll now be introducing a whole new language
to your application (JavaScript), and you'll have to deal with having some data not
participating in ViewState (as we saw in the button click event).
Another consideration is the impact AJAX will have on the usability of your
Web site. Even though the ultimate gift of AJAX is to create more responsive
interfaces, developers should keep two things in mind. First, and most obviously,
AJAX is dependent on JavaScript. We all know that some users disable JavaScript,
and that some standards (such as the Canadian government Common Look and Feel
[think Canada's 508]) require that Web sites work with or without JavaScript. So,
you shouldn't assume that the AJAX functionality is working, and you should have
your application fall back to more normal Web processing if it isn't available. Second,
AJAX applications might be unfamiliar (even if it's superior) to the way users are
used to using applications. An example of this is that a page that does various things
through AJAX might not behave with the Back button, Favorites menu, and other
browser features in the way a user thinks it should.
Conclusion
AJAX isn't just a hyped upcoming technology; instead, it's a concrete
framework that can provide you with alternative solutions for your everyday
problems when building Web applications. Ajax.NET makes it easy for ASP.NET
developers to embrace AJAX. The three examples we looked at, along with the
downloadable projects, are meant to help you understand how to use AJAX and
Ajax.NET, and also provide a simple playground for you to try out some of your own
ideas. AJAX is about more than creating neat and cool applications; it can truly lead
to improved customer satisfaction and a competitive advantage. Some of the high-
level concepts being discussed for Atlas could significantly improve on the products
we deliver. Personally, the best implementations of AJAX I've seen are fairly
lightweight and just feel right. Your own implementations should be an equally
positive experience for your users. Remember though, given a problem, AJAX
probably won't be the only solution, and it might not be the best. Now, let's prove
that the ASP.NET community is second to none, and let's clean house.