Category :
- ASP.NET AJAX in Person (1)
- Conclusion (1)
- The AJAX Core Engine (1)
- The AJAX Revolution (1)
The W3C DOM consists of three levels that indicate, for the browser, three different levels of
adherence to the standard. For more information, take a look at http://www.w3.org/DOM.
The DOM is made of nodes, and each node is an object. For a Web page, each node maps to
an object that represents an HTML tag. The object, therefore, has properties and methods that
can be applied to an HTML tag. There are three fundamental operations you can accomplish
on a node: find the node (including related nodes such as children, parent, or sibling nodes),
create a node, and manipulate a node.
Identifying a particular node is easy as long as the page author knows the ID of the corresponding
element. In this case, you use the following standard piece of code:
var node = document.getElementById(id);
In particular, if there are multiple elements sharing the same ID value, the method returns the
first object in the collection. This method is supported in the DOM Level 1 and upper levels.
Another interesting method to find elements is the following:
var coll = document.getElementsByTagName(tagname);
The method retrieves a collection of all objects based on the same HTML tag. For example, the
method retrieves a collection of all or all tags in the page.
Related DOM objects are grouped in node lists. Each node has a name, type, parent, and collection
of children. A node also holds a reference to its siblings and attributes. The following
code snippet shows how to retrieve the parent of a node and its previous sibling:
var oParent = oNode.parentNode
var oPrevious = oNode.previousSibling
How can you modify the contents of a node? The easiest and most common approach entails
that you use the innerHTML property:
var node = document.getElementById("button1");
node.innerHTML = "Hey click me";
The innerHTML property is supported by virtually all browsers, and it sets or retrieves the
HTML between the start and end tags of the given object. Some browsers such as Internet
Explorer also support the innerText property. This property is designed to set or retrieve the
text inside of a given DOM object. Unfortunately, this property is not supported by all browsers.
It exists in Internet Explorer and Safari but, for example, it is not supported by Firefox.
Firefox, on the other hand, supports a property with a similar behavior but a different name—
textContent.
Note : The advent of the Microsoft AJAX Client Library (discussed in Chapter 2, “The
Microsoft Client Library for AJAX”) shields developers from having to know much about the
little differences between the DOM implementation of the various browsers. For example, you
should know about innerText and textContent if you’re embedding your own JavaScript in the
page; however, you don’t have to if you rely on the AJAX Client Library to refresh portions of
the displayed page.
Note : Finally, note that you should not check the user agent string to figure out whether
the current browser supports a given feature. You should check the desired object instead.
For example, to know whether the browser supports innerText, you’re better off running the
following code:
var supportsInnerText = false;
var supportsInnerText = false;
if (temp != undefined)
supportsInnerText = true;
...
In this way, you directly check the availability of the property without having to maintain a list
of browsers.
Nodes are created using the createElement method exposed only to the document object.
Alternatively, you can add new elements to the document hierarchy by modifying the
innerHTML property value, or by using methods explicit to particular elements, such as the
insertRow and insertCell methods for the table element. Here’s an example:
// Create an element
var oImg = document.createElement("");
...
// Create a new option for the SELECT element
var oOption = new Option(text, id);
control.options.add(oOption);
With this information, I have only scratched the surface of the DOM implementation in the
various browsers. Nonetheless, the DOM is a key part of the AJAX jigsaw puzzle and deserves
a lot of attention and skilled use. For a primer, you can take a look at http://
msdn.microsoft.com/workshop/author/dom/domoverview.asp.
The DOM is a standard API exposed by the browser in which a displayed page has a treebased
structure. Each node in the logical tree corresponds to an object. On the other hand,
the name “Document Object Model” hints at an object model in the common interpretation
of the object-oriented design terminology. A Web page—the document—is modeled through
objects. The model includes the structure and behavior of a document. Each node in the logical
tree is not static data; rather, it is a live object with a known behavior and its own identity.
The DOM is a platform-independent and language-neutral representation of the contents of
a Web page that scripts can access and use to modify the content, structure, and style of the
document.
For AJAX, it’s all about exchanging data with a remote server. But once the data is downloaded
out-of-band on the client, what can you do with that? The DOM provides an outlet for the data
to flow into the current page structure and update it.
Web pages that shoot out-of-band calls need to have one or more trigger events that, when properly
handled with a piece of JavaScript code, place the request via the XMLHttpRequest object.
Trigger events can only be HTML events captured by the browser’s DOM implementation.
The JavaScript code should initiate and control the remote URL invocation, as shown in the
following code:
The sample function accepts two strings: the URL to call and the parameter list. Note that the
format of the query string is totally arbitrary and can be adapted at will in custom implementations.
The URL specified by the programmer is extended to include a couple of parameters.
The first parameter—named outofband in the example—is a Boolean value and indicates
whether or not the request is going to be a custom callback request. By knowing this, the target
page can process the request appropriately. The second parameter—named param in the
example—contains the input parameters for the server-side code.
The host ASP.NET page looks like the following code snippet:
Testing Out-of-band
The code-behind class is shown in the following listing:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (IsOutOfBand())
return;
if (!IsPostBack)
PopulateList();
}
private bool IsOutOfBand()
{
bool isCallback = false;
isCallback = String.Equals(Page.Request.QueryString["callback"],
"true",
StringComparison.OrdinalIgnoreCase);
if (isCallback)
{
string param = Request.QueryString["param"].ToString();
Response.Write(ExecutePageMethod(param));
Response.Flush();
Response.End();
return true;
}
return false;
}
private void PopulateList()
{
SqlDataAdapter adapter = new SqlDataAdapter(
"SELECT employeeid, lastname FROM employees",
"SERVER=(local);DATABASE=northwind;UID=...;");
DataTable table = new DataTable();
adapter.Fill(table);
EmployeeList.DataTextField = "lastname";
EmployeeList.DataValueField = "employeeid";
EmployeeList.DataSource = table;
EmployeeList.DataBind();
}
string ExecutePageMethod(string eventArgument)
{
return "You clicked: " + eventArgument;
}
}
A couple of issues deserve more attention and explanation. The first one is the need to find
out whether the request is an out-of-band call or a regular postback. Next, we need to look at
the generation of the response. The IsOutOfBand method checks the outofband field in the
posted form. If the outofband field is found, the request is served and terminated without going
through the final part of the classic ASP.NET request life cycle—events for changed values,
postback, pre-rendering, view-state serialization, rendering, and so forth. An out-of-band
request is therefore short-circuited to return more quickly, carrying the least data possible.
What does the page do when an out-of-band call is placed? How does it determine the
response? Most of the actual AJAX-based frameworks vary on this point, so let’s say it is arbitrary.
In general, you need to define a public programming interface that is invoked when an
out-of-band call is made. In the sample code, I have a method with a contracted name and
signature—ExecutePageMethod—whose output becomes the plain response for the request. In
the sample code, the method returns and accepts a string, meaning that any input and output
parameters must be serializable to a string.
string param = Request.QueryString["param"].ToString();
Response.Write(ExecutePageMethod(param));
Response.Flush();
Response.End();
As in the code snippet, the response for the out-of-band request is the output of the method.
No other data is ever returned; and no other data except for the parameters is ever sent. In this
particular implementation, there will be no view state sent and returned.
Important Although you’ll probably never get to write any such code, be aware that thus
far I’ve just provided a minimal but effective description of the underlying mechanism common
to most frameworks that supply AJAX-like functionality. Each framework encapsulates a
good number of details and adds new services and capabilities. At its core, though, this is
how AJAX libraries work.
Note : Although a homemade AJAX framework might not be recommended, it’s not impossible
to write. The fact that more than 100 AJAX frameworks have been counted just demonstrates
that writing AJAX homemade solutions is not a mission-impossible task. Personally,
I would consider it only as a way to enrich existing applications with quick and dirty AJAX
functionality limited to placing remote, non-browser-led calls.
The response of the request is available in two formats: as raw text and as an XML document.
The responseText property is empty if the state is 0 through 2—that is, no data has been
received yet. When the state transitions to 3 (receiving data), the property contains the data
received so far, interpreted using the character encoding specified in the response. If no character encoding was specified, it employs UTF-8.
Most AJAX frameworks obtain an instance of the XMLHttpRequest object for the current
browser using code that looks like the following:
var xmlRequest, e;
try {
xmlRequest = new XMLHttpRequest();
}
catch(e) {
try {
xmlRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e) {
}
}
The code first tries to instantiate the internal XMLHttpRequest object and opts for the ActiveX
object in the case of failure. As you can see, the creation of the object requires an exception to
be caught when the browser is Internet Explorer 6.0 or any older versions. Such a code will
work unchanged (and won’t require any exception) in Internet Explorer 7.0.
Note : Checking the browser’s user agent and foregoing the exception is fine as well.
However, ASP.NET AJAX Extensions uses the preceding code because it makes the overall
library independent from details of user agent strings and browser details. In this way, you do
“object detection” instead of “browser detection.” The final result, though, is the same. The
exception is fired only if the browser is Internet Explorer older than version 7.0 or any other
browser that doesn’t support AJAX functionalities. If you’re building your own AJAX framework,
you need to check the user agent only against Internet Explorer.
The open method prepares the channel for the request; no physical socket is created yet,
though. To execute a POST statement, you need to add the proper content-type header. The
Boolean argument indicates whether the operation is asynchronous:
xmlRequest.open("POST", url, false);
xmlRequest.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
xmlRequest.send(postData);
The send method opens the socket and sends the packet. In the preceding code snippet, the
method returns only when the response has been fully received.
An asynchronous request requires slightly different code:
xmlRequest.open("POST", url, true);
xmlRequest.onreadystatechange = CallbackComplete;
xmlRequest.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
xmlRequest.send(postData);
The CallbackComplete element is a placeholder for a JavaScript function that retrieves and processes the response generated by the request.
Note : that the function assigned to the onreadystatechange member will be invoked whenever
readyState changes value. Possible values for the state are the integers ranging from 0 through
4, which mean “Uninitialized,” “Open method called successfully,” “Send method called successfully,”
“Receiving data,” and “Response received,” respectively. The CallbackComplete
framework-specific function will generally check that state and proceed.
The XMLHttpRequest object is designed to perform one key operation: sending an HTTP
request. The request can be sent either synchronously or asynchronously. The following listing
shows the programming interface of the object as it results from the W3C working draft at
the time of this writing:
interface XMLHttpRequest {
function onreadystatechange;
readonly unsigned short readyState;
void open(string method, string url);
void open(string method, string url, bool async);
void open(string method, string url, bool async, string user);
void open(string method, string url, bool async,
string user, string pswd);
void setRequestHeader(string header, string value);
void send(string data);
void send(Document data);
void abort();
string getAllResponseHeaders();
string getResponseHeader(string header);
string responseText;
Document responseXML;
unsigned short status;
string statusText;
};
Using the component is a two-step operation. First, you open a channel to the URL and specify
the method (GET, POST, or other) to use and whether you want the request to execute
asynchronously. Next, you set any required header and send the request. If the request is a
POST, you pass to the send method the body of the request.
The send method returns immediately in the case of an asynchronous operation. You write an
onreadystatechange function to check the status of the current operation and, using that function,
figure out when it is done.
As mentioned, the XML in the name of the component means little and in no way limits the
capabilities of the component. In spite of the XML prefix, you can use the object as a true automation
engine for executing and controlling HTTP requests, from client code generated by
ASP.NET pages or the Windows shell, or Visual Basic 6.0 or C++ unmanaged applications. Using
the XMLHttpRequest COM object from within .NET applications is nonsensical, as you can find
similar functionality in the folds of the System.Net namespace in the .NET Framework.
Important : If you’re going to use Microsoft ASP.NET AJAX Extensions or any other AJAXlike
framework for building your applications, you’ll hardly hear about the XMLHttpRequest
object, much less use it directly in your own code. ASP.NET AJAX Extensions completely
encapsulates this object and shields page authors and application designers from it. You
don’t need to know about XMLHttpRequest to write great AJAX applications, no matter how
complex and sophisticated they are. However, knowing the fundamentals of XMLHttpRequest
can lead you to a better and more thorough understanding of the platform and to more
effective diagnoses of problems.
Implemented as a COM component for historical reasons on Internet Explorer browsers, the
XMLHttpRequest object has finally become a browser object with Internet Explorer 7.0. All
potential security concerns are removed at the root, and AJAX frameworks can be updated
to use the same syntax for creating the XMLHttpRequest object regardless of the browser:
var proxy = new XMLHttpRequest();
In addition, this change in Internet Explorer 7.0 completely decouples AJAX-like functionality
in ASP.NET from an ActiveX-enabled environment.
Mozilla adopted XMLHttpRequest immediately after its first release with Internet Explorer 5.0.
However, in Mozilla-equipped browsers the XMLHttpRequest object is part of the browser’s
object model and doesn’t rely on external components. Put another way, a Mozilla browser
such as Firefox publishes its own XMLHttpRequest object into the scripting engine and never
uses the COM component, even when the COM component is installed on the client machine
and is part of the operating system. Figure 1-4 shows the different models in Internet Explorer
(up to version 6.0) and Mozilla browsers.
As a result, in Mozilla browsers XMLHttpRequest looks like a native JavaScript object and can
be instantiated through the classic new operator:
// The object name requires XML in capital letters
var proxy = new XMLHttpRequest();
When the browser is Internet Explorer, the XMLHttpRequest object is instantiated using the
ActiveXObject wrapper, as shown here:
var proxy = new ActiveXObject("Microsoft.XmlHttp");
Generally, AJAX-style frameworks check the current browser and then decide about the route
to take.
Needless to say, as implemented in Mozilla browsers the XMLHttpRequest functionality is
somewhat safer, at least in the sense it doesn’t require users to change their security settings
for the browser.
When the XMLHttpRequest object was first released, the Component Object Model (COM)
was ruling the world at Microsoft. The extensibility model of products and applications was
based on COM and implemented through COM components. In the late 1990s, the right and
natural choice was to implement this new component as a reusable automation COM object,
named Microsoft.XmlHttp.
Various versions of the same component (even with slightly different names) were released
over the years, but all of them preserved the original component model—COM. Internet
Explorer 6.0, for example, ships the XMLHttpRequest object in the form of a COM object.
Where’s the problem?
COM objects are external components that require explicit permission to run inside of a Web
browser. In particular, to run the XMLHttpRequest object and subsequently enable any AJAX
functionality built on top of it, at a minimum a client machine needs to accept ActiveX components
marked safe for scripting. (See Figure 1-3.)
The XMLHttpRequest object is certainly a safe component, but to enable it users need to lessen
their security settings and accept any other component “declared” safe for scripting that is
around the Web sites they visit.
Important : The internal implementation of XMLHttpRequest is disjointed from the implementation
of any AJAX-like frameworks, such as Microsoft ASP.NET AJAX. Under the hood,
any framework ends up calling the object as exposed by, or available in, the browser.
Note : The XMLHttpRequest object originally shipped as a separate component with Internet
Explorer 5.0 back in the spring of 1999. It is a native component of all Microsoft operating
systems that have shipped since. In particular, you’ll certainly find it installed on all machines
that run Windows 2000, Windows XP, and newer operating systems.
The proxy component (for example, the XMLHttpRequest object) sends a regular HTTP
request and waits, either synchronously or asynchronously, for it to be fully served. When the
response data is ready, the proxy invokes a user-defined JavaScript callback to refresh any portion
of the page that needs updating. Figure 1-2 provides a graphical overview of the model.
All browsers know how to replace an old page with a new page; until a few years ago, though,
not all of them provided an object model to represent the current contents of the page. (Today,
I can hardly mention a single modern, commercially available browser that doesn’t expose a
read/write page DOM.) For browsers that supply an updatable object model for HTML pages,
the JavaScript callback function can refresh specific portions of the old page, thus making
them look updated, without a full reload.
The term AJAX was coined in 2005. It originated in the Java community and was used in reference
to a range of related technologies for implementing forms of remote scripting. Today,
any form of remote scripting is generally tagged with the AJAX prefix. Modern AJAX-based
solutions for the Windows platform are based on the XMLHttpRequest object. Google Maps
and Gmail are the two most popular Web applications designed according to AJAX patterns
and techniques. For AJAX, these were certainly the killer applications that established its usefulness and showed its potential.
Two combined elements make an AJAX application live and thrive. On one hand, you need to
serve users fresh data retrieved on the server. On the other hand, you need to integrate new
data in the existing page without a full page refresh.
Browsers generally place a new request when an HTML form is submitted either via clientside
script or through a user action such as a button click. When the response is ready, the
browser replaces the old page with the new one. Figure 1-1 illustrates graphically this traditional
approach.
The chief factor that enables remote scripting is the ability to issue out-of-band HTTP requests.
In this context, an out-of-band call indicates an HTTP request placed using a component that
is different from the browser’s built-in module that handles the HTML form submission (that
is, outside the traditional mechanism you see in Figure 1-1). The out-of-band call is triggered
via script by an HTML page event and is served by a proxy component. In the most recent
AJAX solutions, the proxy component is based on the XMLHttpRequest object; the proxy component was a Java applet in the very first implementation of RS.
(RPC) appeared around 1997. Microsoft, in particular, pioneered this field with a technology
called Remote Scripting (RS).
RS employed a Java applet to pull in data from a remote Active Server Pages (ASP)-based URL.
The URL exposed a contracted programming interface through a target ASP page and serialized
data back and forth through plain strings. On the client, a little JavaScript framework
received data and invoked a user-defined callback to update the user interface via Dynamic
HTML or similar techniques. RS worked on both Internet Explorer 4.0 and Netscape Navigator
4.0 and older versions.
Later on, Microsoft replaced the Java applet with a Component Object Model (COM) object
named XMLHttpRequest and released most of the constraints on the programming interface
exposed by the remote URL—for example, no more fixed ASP pages. At the same time, community
efforts produced a range of similar frameworks aimed at taking RS to the next level
and building a broader reach for solutions. The Java applet disappeared and was replaced by
the XMLHttpRequest object.
This model was just fine in the beginning of the Web age when pages contained little more
than formatted text, hyperlinks, and some images. The success of the Web has prompted
users to ask for increasingly more powerful features, and it has led developers and designers
to create more sophisticated services and graphics. As an example, consider advertising.
Today, most pages—and often even very simple pages, such as blog pages—include ad rotators
that download quite a bit of stuff on the client.
As a result, pages are heavy and cumbersome—even though we still insist on calling them
“rich” pages. Regardless of whether they’re rich or just cumbersome, these are the Web pages
of today’s applications. Nobody really believes that we’re going to return to the scanty and
spartan HTML pages of a decade ago.
Given the current architecture of Web applications, each user action requires a complete
redraw of the page. Subsequently, richer and heavier pages render slowly and as a result produce
a good deal of flickering. Projected to the whole set of pages in a large, portal-like application,
this mechanism is just perfect for unleashing the frustrations of the poor end user.
Although a developer can build a page on the server using one of many flexible architectures
(ASP.NET being one such example), from the client-side perspective Web pages were originally
designed to be mostly static and unmodifiable. In the late 1990s, the introduction of
Dynamic HTML first, and the advent of a World Wide Web Consortium (W3C) standard for
the page document object model later, changed this basic fact. Today, the browser exposes the
whole content of a displayed page through a read/write object model. In this way, the page
can be modified to incorporate changes made entirely on the client-side to react to user inputs.
(As we’ll see, this is a key factor for AJAX and ASP.NET AJAX solutions.)
Based on the URL typed in the address bar, the browser displays a page to the user. The page
is ultimately made of HTML markup and contains one or more HTML forms. The user enters
some data, and then instructs the browser to submit the form to an action URL.
the markup returned by the Web server. The browser-to-server communication employs
the classic HTTP protocol. As is widely known, the HTTP protocol is stateless, which means
that each request is not related to the next and no state is automatically maintained. (The state
objects we all know and use in, say, ASP.NET are nothing more than an abstraction provided
by the server programming environment.)
Communication between the browser and the Web server occurs through “forms.” From a
user’s perspective, the transition occurs through “pages.” Each user action that originates a
new request for the server results in a brand new page (or a revamped version of the current
page) being downloaded and displayed.
Let’s briefly explore this model a bit further to pinpoint its drawbacks and bring to the surface
the reasons why a new model is needed.
We are all witnessing and contributing to an interesting and unique phenomenon—the Web is
undergoing an epochal change right before our eyes as a result of our actions. As drastic as it
might sound, the Web revolutionized the concept of an application. Only eight years ago, the
majority of developers considered an application far too serious a thing to reduce it to an
unordered mix of script and markup code. In the late 1990s, the cost of an application was
sweat, blood, tears, and endless debugging sessions. According to the common and semiserious
perception there was neither honor nor fame for the “real” programmer in writing
Web applications.
Note : In the late 1990s, though, a number of Web sites were designed and built. Some of
them grew incredibly in the following years to become pillars of today’s world economy and
even changed the way we do ordinary things. Want some examples? Google, Amazon, eBay.
Nonetheless, a decade ago the guys building these and other applications were sort of
avant-garde developers, perhaps even just smart and game amateurs.
Since then, the Web has evolved significantly. And although 10 years of Web evolution has
resulted in the building of a thick layer of abstraction on the server side, it hasn’t changed the
basic infrastructure—HTTP protocol and pages.
The original infrastructure—one that was simple, ubiquitous, and effective—was the chief factor
for the rapid success of the Web model of applications. The next generation of Web applications
will still be based on the HTTP protocol and pages. However, the contents of pages
and the capabilities of the server-side machinery will change to provide a significantly richer
user experience—as rich as that of classic desktop Windows applications.
Note : As we’ll see in greater detail in Chapter 8, “Building AJAX Applications with ASP.NET,”
AJAX applications have a number of plusses but also a few drawbacks. Overall, choosing an
AJAX application rather than a classic Web application is simply a matter of weighing the
trade-offs. An AJAX application certainly gives users continuous feedback and never appears
held up by some remote operation. On the other hand, AJAX applications are not entirely
like desktop applications, and their capabilities in terms of graphics, multimedia, and hardware
control are not as powerful as in a regular (smart) client. In the end, AJAX applications
are just one very special breed of a Web application; as such, they might require some code
refactoring to deliver the expected performance and results
Gone are the days when a Web application could be architected and implemented as a collection of related and linked pages. The advent of the so-called AJAX model is radically modifying the user’s perception of a Web application, and it is subsequently forcing developers to apply
newer and richer models to the planning and implementation of modern Web applications.
But what is the AJAX model, anyway?
AJAX is a relatively new acronym that stands for Asynchronous JavaScript and XML. It is a sort ofblanket term used to describe highly interactive and responsive Web applications. What’s the
point here? Weren’t Web applications created about a decade ago specifically to be “interactive,”
“responsive,” and deployed over a unique tool called the browser? So what’s new today?
The incredible success of the Internet has whetted people’s appetite for Web-related technology
beyond imagination. Over the years, the users’ demand for ever more powerful and Webexposed
applications and services led architects and developers to incorporate more and
more features into the server platform and client browser. As a result, the traditional pattern
of Web applications is becoming less adequate every day. A radical change in the design and
programming model cannot be further delayed.
At the current state of the art, the industry needs more than just an improved and more powerful
platform devised along the traditional guidelines and principles of Web applications—a
true paradigm shift is required. AJAX is the incarnation of a new paradigm for the next generation
of Web applications that is probably destined to last for at least the next decade.
From a more developer-oriented perspective, AJAX collectively refers to a set of development
components, tools, and techniques for creating highly interactive Web applications that give
users a better experience. According to the AJAX paradigm, Web applications work by
exchanging data rather than pages with the Web server. From a user perspective, this means
that faster roundtrips occur and, more importantly, page loading and refresh is significantly
reduced. As a result, a Web application tends to look like a classic desktop Microsoft Windows