Background
Asynchronous JavaScript and XML or AJAX has been the revolutionary technology that enabled rich user experience over the web, much like desktop rich user experience. In this series, I will describe my journey of learning AJAX and some simple steps that will get you started with this simple but powerful technology.
Introduction
AJAX enables web developers to dynamically update a web page via background asynchronous posts to the server. Hence, it removes the necessity of sending the entire page back to the server and causing global refresh in the browser. This results in the following major benefits:
- Rich user experience – A web user doesn’t have to wait until the entire page is loaded. Nor is he / she distracted by visual information loss during the page reloads. AJAX also can be used to display progress information while a sub-portion of the page is being updated / loaded from the server.
- Server scalability – Since only minimal information is exchanged between the client and the server, the server can serve more clients in turn with the same amount of resources (memory, CPU). This helps in increasing server scalability.
- Client efficiency – The client browser only needs to update a sub-portion of already loaded web page as opposed to parsing and displaying the entire page all over again.
Figure 1 – Classic Web Application Model
Figure 2 – AJAX Web Application Model
The solid lines depict synchronous operations whereas the gray lines depict asynchronous operations.
Building Blocks of AJAX
AJAX is not a technology by itself. It is an outcome of several collaborating technologies that fit their respective roles in the overall end to end asynchronous HTTP request / response process. The major building blocks involved in AJAX web application model are as follows:
This example shows how to add a shim type of the same name XMLHttpRequest
if the browser doesn’t support it out of the box. For a complete reference on XMLHttpRequest
JavaScript class, refer to Mozilla Developer Center page.
I highly recommend reading a book that explains the above technologies in depth to get your basics right. I personally read Beginning Ajax with ASP.NET and found it a very good start for beginners. However, later chapters in the book are outdated as technologies that they mention, especially Microsoft Atlas have considerably changed since the book was released.
First AJAX Experience
In the beginning of this blog, I promised you to present AJAX in a very approachable style. For years, I had ignored learning this technology as I considered it to be very non-standard and hacky then. Now I differ in my opinion owing to the fact that there are many technologies in the AJAX web model that have been recognized as industry standards and are now W3C compliant. Anyways, let’s now see things in action! Create an ASP.NET web application in Visual Studio where you will test your first AJAX code. Then create an XML file note.xml in the project and overwrite its content with the following:
="1.0"="iso-8859-1"
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
Next create an HTML document in the project ajax.htm with the following content:
<html>
<head><title>First AJAX Example</title></head>
<script type="text/javascript">
var request;
var READYSTATE_COMPLETE = 4;
if (typeof(XMLHttpRequest) == "undefined") {
XMLHttpRequest = function() {
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP"); }
catch(e) {}
try { return new ActiveXObject("Microsoft.XMLHTTP"); }
catch(e) {}
throw new Error("This browser does not support XMLHttpRequest.");
};
}
function ReadXmlFile() {
request = new XMLHttpRequest();
request.open('GET', 'note.xml', true);
request.onreadystatechange = DisplayXmlFile;
request.send(null);
}
function DisplayXmlFile() {
if (request.readyState == READYSTATE_COMPLETE) {
xmlSpan.innerText = request.responseText;
}
}
</script>
<body>
<span id="xmlSpan"></span><input type="button" onclick="ReadXmlFile();" value="ReadXml" />
</body>
</html>
Finally, fire the app in the browser and open ajax.htm. You will see if you hit the ReadXml
button, the xmlSpan
span gets populated with the content of note.xml without refreshing the page as shown in Figure 3 below.
Figure 3 – Running the first AJAX example
Security Note
In order to ensure online security and to prevent cross scripting attacks, the browsers limit the XMLHttpRequest
object to only request resources from the same domain as the domain of the web application. You can verify this in the above example. Instead of requesting note.xml, try requesting http://www.w3schools.com/XML/note.xml which has the same content. Running the application will not allow the XML file to be fetched. Replace it again with note.xml and it will work again.
AJAX Frameworks
In recent years, the use of AJAX in major web portals have revolutionized online user experience. Although Microsoft was the first company to make use of AJAX, it was Google which truly captured the power of this technology and set a new standard for online user experience. Several frameworks have been built to increase developer productivity while developing AJAX based web applications. These frameworks can be categorized into the following major categories:
- Client side frameworks – JavaScript libraries/frameworks that help developers reuse/leverage client side JavaScript code.
- Server side frameworks – Server side code generators/injectors combined with capabilities to extend client side AJAX JavaScript code to achieve extensibility and reusability in AJAX web application development.
Each of the following categories have their own benefits and drawbacks. The decision to pick one over the other depends in the nature of application being developed and platforms being used to develop those applications. A lot of times, developers also pick a combination of tools belonging to different categories and integrate them together to achieve the desired end product. I will walk you through an example of each of the following categories in the upcoming sections.
Client Side Frameworks
Many efforts have been made to enhance JavaScript to support AJAX via reusable libraries. Quite possibly, the biggest effort is the conception of jQuery – a lightweight library that emphasizes interaction between JavaScript and HTML. Microsoft has already adopted this framework which is now shipping with ASP.NET MVC Framework and in the near future will be a part of upcoming Visual Studio 2010 release. Let us rewrite our previous example using jQuery. Again, follow the previous example as is except this time your HTML page should have the following content:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>AJAX with jQuery</title>
</head>
<script src="Scripts/jquery-1.3.2.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#ReadButton").click(function() {
$.ajax({
type: "GET",
url: "note.xml",
success: function(msg) {
$("#xmlSpan").attr("innerText", msg.xml);
}
});
});
});
</script>
<body>
<span id="xmlSpan"></span>
<input type="button" id="ReadButton" value="ReadXml" />
</body>
</html>
The script to fetch note.xml this time is so much more concise! Also note that we didn’t need to do anything funky on the server side to make it work. We didn’t have to create XMLHttpRequest
object and check for browser type while doing so. Also, we didn’t have to declare constants to check states for XMLHttpRequest
object. Just a precise subscription to success
event got our callback going!
Ok you must be wondering well, the above works well but what if HTTP POST
is required instead of a GET
and how does one go about executing business logic on the backend while making asynchronous HTTP POST
requests. Well, the answer is simple. We can use POST
version of jQuery AJAX call to achieve the same. We shall see this approach in the scenario below.
Consider that you want to call a method GetPerson
on your backend ASP.NET page that gives you a custom Person
object. Let’s assume that this Person
object is to be processed on the client and displayed to the user. Let’s see how we can go about doing it.
In order to achieve the above scenario, we must understand how serialization works between a backend .NET managed object and JavaScript objects. Any object in JavaScript can be serialized to JSON (JavaScript Object Notation) format. As well as any JSON object can be deserialized into a JavaScript object. JSON is really a format for structured data interchange between systems. The BNF for object denotation in JSON is as follows:
JSON Notation := { } | {KeyValuePair}
KeyValuePair := Key : Value | KeyValuePair, Key : Value
Key := String
Value := String | Number | JSON Notation | Array | true | false | null
Array := [ ] | [Value] | [Value, Value]
Hence, if you have a person
object storing FirstName
and LastName
, then the following can be a JSON representation of a Person
instance:
{PersonInstance: {FirstName:John, LastName:Rambo}}
and an array of Person objects can be represented as :
{PersonList: [{FirstName:John, LastName:Rambo}, {FirstName:Austin, LastName:Powers}]}
The format of JSON closely matches how JavaScript interprets its objects, i.e., in the form of nested key value pairs. Yes, everything in JavaScript, properties, methods, events are just key value pairs of some sort and hence JavaScript objects are nothing but nested dictionaries! If you follow the persistence format of many other vendors, this is usually a strikingly common way of representing objects (Apple also uses a similar plist format to store property lists in MacOS and also in iTunes! For more information about plist, check out its wikipedia page).
Anyhow, now back to our GetPerson
example. We will create a simple ASP.NET page with the following code behind:
using System;
using System.Web.Services;
[Serializable]
public class Person
{
public string FirstName {get;set;}
public string LastName {get;set;}
}
public partial class Person_Page : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
[WebMethod]
public static Person GetPerson(Person person)
{
return new Person { FirstName = person.FirstName, LastName = person.LastName };
}
}
There is one static
web method called GetPerson
that accepts a parameter of type Person
. Person
really contains the first name and the last name of a person. GetPerson
then simply returns a new Person
object with the same first and last name. One important thing to note is that Person
object is marked with a Serializable
attribute. In CLR, if an object is marked with a Serializable
attribute, then it can be serialized into any given format / and or built from any format back as an object. Also note the public static
visibility type and WebMethod
attribute on GetPerson
method. This is essential to expose a method to be called by client web requests. We shall see how we can call this method from the client code below.
<%@ Page Language="C#"
AutoEventWireup="true" CodeFile="Person_Page.aspx.cs"
Inherits="Person_Page" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>jQuery POST Example</title>
</head>
<script src="Scripts/jquery-1.3.2.js"
type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#GetPerson").click(function() {
var firstname = $("#txtFirstName").val();
var lastname = $("#txtLastName").val();
content = "{'person':
{'FirstName':'" + firstname +
"', 'LastName':'" + lastname + "'}}";
$.ajax({
type: "POST",
url: "Person_Page.aspx/GetPerson",
data: content,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
var fullName = msg.d.LastName + ", " + msg.d.FirstName;
$("#lblFullName").text(fullName);
}
});
});
});
</script>
<body>
<form id="form1" runat="server">
<div>
First Name: <input type="text" id="txtFirstName" />
Last Name: <input type="text" id="txtLastName" />
<br />
<input type="button"
id="GetPerson" value="GetPerson"></input>
<span id = "lblFullName"></span>
</div>
</form>
</body>
</html>
We have two text fields here txtFirstName
and txtLastName
that capture the first and the last name of the person
respectively. Then, we have a GetPerson
button that makes the AJAX call to the code behind of the page and tries to call a web method GetPerson
and passes in the constructed JSON from txtFirstName
and txtLastName
fields via content string
variable. Once the response is received back from the server, the text of the span lblFullName
is updated to show the full name in the format LastName
, FirstName
. Following is the screenshot while running the above code:
Figure 4 – jQuery POST Example in action
As can be seen when the CLR receives the POST
requests, it queries the HTTP ContentType
field value. Since it is specified as application / json, hence it deserializes the person
object from JSON to actual Person
instance and also serializes the resulting Person
object from GetPerson
back to JSON. Also notice the JSON string
construction from client script in content string
object. We specify the key of the object to be ‘person
’ which is the same name as the formal parameter name of Person
object in GetPerson
web method. This allows for binding of parameters during the call so value can be passed correctly to the web method.
Server Side Frameworks
Server side frameworks dynamically generate and inject AJAX JavaScript snippets into server processed forms, so developers are not bothered writing JavaScript every time they desire AJAX style functionality in their web applications. We already have seen above that JSON and JavaScript correspond quite well to each other and one can be projected to another and vice versa. Armed with this fact, server side frameworks generate proxy JavaScript objects on the fly that correspond with backend data structures. They also inject code that call backend methods asynchronously and pass proxies to and from client browser.
There are many popular sever side AJAX frameworks such as Microsoft ASP.NET AJAX, AjaxPro, ComfortASP.NET and MagicAjax.NET. In addition, Microsoft has started a community effort to build more server side controls to bring web experience closer to desktop experience via a community project called ASP.NET AJAX Control Toolkit (although last time I checked there were quite a few bugs in this toolkit and some controls such as AutoComplete
were completely broken). I must also mention that Microsoft ASP.NET AJAX server framework also contains a client side JavaScript library called Microsoft AJAX library (talk about confusing names) that closely mimics much of OO features present in managed languages such as inheritance, interfaces, etc. Microsoft AJAX library can be downloaded from here.
However, one must realise serious implications of using various server side frameworks in code. Most of the time, these limitations are not very well documented. One common limitation is the use of conflicting HTTP handlers and HTTP modules in ASP.NET projects. HTTP modules and handlers are HTTP request handlers that get executed way before ASP.NET gets to the requests in the application pipeline. Server side frameworks usually utilize these components to inject code into HTML response via JavaScript tags. However, if there are more than one server frameworks used (maybe for different purposes than AJAX), then they might conflict and suppress functionality offered by other frameworks by ‘stealing’ the HTTP requests first.
Another major limitation of server side frameworks is the way they perform asynchronous HTTP requests. ASP.NET AJAX framework for example relies heavily on ASP.NET ViewState
object. Hence, it is impossible to issue requests from web user controls (commonly known as partial views or *.ascx) using this framework. It is also not compatible with ASP.NET MVC framework. Hence, it is important to perform a background study of a framework and ensure that it is compatible with existing frameworks being used in your web applications.
Let us see an example of using server side framework. For the purpose of this example, I will use AjaxPro framework. You can download AjaxPro framework for free from its website. To use this framework, create an ASP.NET web application and simply reference the downloaded assembly (AjaxPro.dll or AjaxPro2.dll depending on the version you download from the website) from your project.
Next, add the following lines in web.config (Note: If you already have a httpHandlers
section, just add the ‘add
’ tag from below):
<httpHandlers>
<add verb="POST,GET" path="ajaxpro/*.ashx"
type="AjaxPro.AjaxHandlerFactory,AjaxPro.2"/>
</httpHandlers>
The code above implies that whatever request POST
/GET
is received for a resource with extension ashx within the ajaxpro folder must be forwarded to AjaxPro.AjaxHandlerFactory
http handler defined in AjaxPro.2.dll assembly.
Next, we will add a new ASP.NET page named AjaxPro_Page
to the project. The first thing we need to do in order to hook up this page to AjaxPro
http handler is to register it with AjaxPro. We do this via AjaxPro.Utility.RegisterTypeForAjax
call from within page’s Page_Load
method as follows:
protected void Page_Load(object sender, EventArgs e)
{
AjaxPro.Utility.RegisterTypeForAjax(typeof(AjaxPro_Page));
}
The next step is to define method(s) on this page that will be called from within this page by the client code. For the purpose of this example, we shall define a GetTime
method that will return server time to the client. It is important to mark this method with AjaxMethod
attribute so a “proxy” code for this method can be generated by the AjaxPro framework. Following is the definition of GetTime
method:
[AjaxMethod]
public DateTime GetTime()
{
return DateTime.Now;
}
At this time, the server part of the code is complete. The complete class should look like follows:
using System;
using AjaxPro;
public partial class AjaxPro_Page : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
AjaxPro.Utility.RegisterTypeForAjax(typeof(AjaxPro_Page));
}
[AjaxMethod]
public DateTime GetTime()
{
return DateTime.Now;
}
}
Let us run this page in browser and see what gets generated on the client side. Run this page in browser and view the source for this page. You will find the following three script
tags that were injected by AjaxPro.AjaxHandlerFactory
http handler that we registered in web.config before:
<script type="text/javascript"
src="/blogtest/ajaxpro/prototype.ashx"></script>
<script type="text/javascript"
src="/blogtest/ajaxpro/core.ashx"></script>
<script type="text/javascript"
src="/blogtest/ajaxpro/converter.ashx"></script>
<script type="text/javascript"
src="/blogtest/ajaxpro/AjaxPro_Page,App_Web_hghu6cj1.ashx">
</script>
The first script is basically the code that enables OO concepts such as inheritance and virtual functions used within the code generated by AjaxPro in later stages. Hence, it defines the base prototype from which all the AjaxPro client code inherits from. The second script generates core related to IFrame, request queues and general request / response logic. The third script is basically the JSON serializer / deserializer for complex .NET types such as System.Collections.Specialized.NameValueCollection
, System.Data.DataSet
, System.Data.DataTableDataTable
, ProfileBaseConverter
and IDictionaryConverter
. This enables you to use this complex data types as return types for your .NET methods and use them seamlessly from AjaxPro generated proxy code.
The last script corresponds to the proxy generated for your code behind. Note that the exact ending of the App_Web_*.ashx handler is random and may not end with hghu6cj1
as in my case. If you navigate to that URL and view the source for the code, you will find something similar to the code below:
AjaxPro_Page_class = function() {};
Object.extend(AjaxPro_Page_class.prototype, Object.extend(new AjaxPro.AjaxClass(), {
GetTime: function() {
return this.invoke("GetTime", {},
this.GetTime.getArguments().slice(0));
},
url: '/blogtest/ajaxpro/AjaxPro_Page,App_Web_hghu6cj1.ashx'
}));
AjaxPro_Page = new AjaxPro_Page_class();
Here, we can clearly see that AjaxPro generates a JavaScript class named AjaxPro_Page_class
and defines invoke code for GetTime
method. What it does exactly is define a class AjaxPro_Page_class
as an empty class and then add GetTime
method to its prototype. This way, any instance of this class or its subclass will have access to the GetTime
method via prototype chaining. Finally, it declares an instance of AjaxPro_Page_class
named AjaxPro_Page
(same name as our server code behind class) so it can be used from our scripts to invoke methods on the code behind.
Now, we need to hook up the client code to call this GetTime
method from AjaxPro_Page
. Well, it's simple. Just replace the code in your AjaxPro_Page.aspx with the following:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="AjaxPro_Page.aspx.cs"
Inherits="AjaxPro_Page" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>AjaxPro Example</title>
</head>
<script src="Scripts/jquery-1.3.2.js"
type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#cmdServerTime").click(function() {
AjaxPro_Page.GetTime(function(result) {
$("#lblServerTime").text(result.value.toString());
});
});
});
</script>
<body>
<form id="form1" runat="server">
<div>
Server Time: <span id="lblServerTime"></span>
<input type="button" id="cmdServerTime"
value="GetServerTime" />
</div>
</form>
</body>
</html>
This code basically declares a span
with id lblServerTime
and a button with id cmdServerTime
. In the page load jQuery, it hooks up the click event of cmdServerTime
to call AjaxPro_Page.GetTime
method, which in turn is hooked up to the anonymous method that replaces the text for the span with the server returned time value from GetTime
method. Run it and you shall see the results similar to the below screenshot:
Figure 5 – AjaxPro example in action
Handling Conflicting HTTP Handlers
As I mentioned before, sometimes multiple http handlers on server may conflict and your application may not work as desired. Hence proper resolution may be required to enable all the handlers to perform in harmony. As an example, if you try to use AjaxPro framework with ASP.NET MVC application, your application will not work out of the box since MVC framework has a powerful URL routing engine that captures all the incoming requests (note that in MVC framework, views are also non-existing resources) including all the resource requests for the non-existing resources the ajaxpro/ non existing folder (refer to web.config above). Hence, we need an exclusion for this rule in the ASP.NET MVC URL routing engine. The following code in the Global.asax.cs will achieve this:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("ajaxpro/{resource}.ashx");
:
}
Debugging Support
As with any application development, debugging support is a must to trace execution points within the code. I test and debug my web applications both in Internet Explorer as well as in Mozilla Firefox. To enable debugging support in Internet Explorer, you can follow the instructions in Jonathan Boutelle’s blog. Good thing about Internet Explorer debugging (I personally use Firefox for all other purposes) is that one can leverage Visual Studio debugger rather than downloading and learning another debugger to debug JavaScript. For Mozilla Firefox, I use Venkman JavaScript Debugger and strongly recommend it as well.
Conclusion
I hope that I was able to provide a good insight into AJAX web development from a beginner’s point of view. There are many tools available which are not covered here but the most important thing is to play around with them and find the best combination that works for your needs. And of course if you learn some, share some! Happy coding!