Chapter 6: ASP.NET AJAX Networking

Chapter 6: ASP.NET AJAX Networking

At the heart of AJAX development is the ability to make asynchronous web service calls from JavaScript code. For several years now, the major web browsers have included an XMLHttpRequest object for making HTTP requests. The XMLHttpRequest object is used to perform out-of-band communications with the server for invoking web services, executing callbacks, and performing partial page updates. This object allows the browser to send requests to the server and to receive data from the server without requiring the entire page to be posted back to the server and subsequently refreshed in the browser.

ASP.NET AJAX provides classes for managing web requests, processing responses, and detecting errors. It also provides support for serializing objects formatted as JSON (JavaScript Object Notation), which makes them readily usable in JavaScript in the browser. JSON is a standard serial format that is more lightweight than XML. In this chapter, you will learn how to use the ASP.NET JavaScript classes to perform networking tasks such as making synchronous and asynchronous HTTP requests, serializing .NET objects to and from JavaScript, and handling errors when web requests do not execute as expected.

The XMLHttpRequest Object

The XmlHttpRequest object was introduced by Microsoft as an ActiveX control for Internet Explorer 5. It was later added to Mozilla 1.0 and Safari 1.2. Now, all serious browsers include support for this object. In Internet Explorer, you pass the name of the object to the ActiveXObject function:


var request = new ActiveXObject("Microsoft.XMLHTTP");

In Firefox and most other browsers, you can simply use the new keyword to create an object directly in JavaScript. In these browsers, the XMLHttpRequest has been added natively to the DOM.


var request = new XMLHttpRequest();

The separate implementations have some common methods, and the behavior is much the same, but ASP.NET AJAX provides objects that give you an abstraction from the differences so you don’t have to worry about browser variations. The ASP.NET AJAX Extensions JavaScript objects are also similar to those available in the .NET Framework, so the object model is more familiar to .NET developers than the native XMLHttpRequest objects.

Because ASP.NET AJAX gives you a set of standard classes to ensure consistent behavior when accessing web resources, rather than using the browser-specific XMLHttpRequest object directly, I won’t go into the details of the XMLHttpRequest object except to point out some security and architectural issues.

XMLHttpRequest Security

The browsers all enforce a common security policy that restricts the XMLHttpRequest object from issuing cross-domain requests. This is a common-sense restriction that prevents a page from possibly sending sensitive data to a third-party site you aren’t specifically addressing. Your JavaScript code can only successfully issue requests against the domain in which the page originated. In fact, the policy prohibits requests that go to a different host, use a different protocol (like HTTP instead of HTTPS), or access the server on a different port. This limits your ability to write so-called mashup applications (the term mashup means to consolidate data from different sources) that leverage a variety of different sources on the web for a synergistic application. For example, JavaScript in a page request to http://www.wrox .com cannot use the XMLHttpRequest object to make calls to http://www.wiley.com (different domain) or to https://www.wrox.com (different protocol) or to http://www.wrox.com:81 (different port) or to http://scripts.wrox.com (different host). You are limited to using the XMLHttpRequest object only for issuing requests against the same domain, host, port, and protocol of the originating page.

Because there are many valid scenarios where you might want to allow mashups from different sites, you can take advantage of some tricks for accessing remote resources. The security restriction does not guard against including IFrame elements in a page that accesses content on different domains, because an IFrame is allowed to pull in a different page, possibly from a different site. You can then use the DOM to relay information to and from JavaScript running in that IFrame. Also, a web service on the originating site can act as a proxy and issue requests against a remote domain on behalf of your web page. The service then returns the remote content to the browser. This involves routing additional requests to your own server, when you would prefer going directly to the servers in another domain, but it satisfies the security constraints of the browser.

Object Properties and Methods

Although there are different implementations of the XMLHttpRequest object in the standard browsers, they share some common APIs. In ASP.NET AJAX applications, you can program against the WebRequest and WebRequestManager objects to simplify your interactions with the XMLHttpRequest object, but it is also helpful to understand what is being done in the underlying object.

Some common methods allow you to initiate a request using send() and to terminate a request by calling abort(). There are also methods for setting and retrieving HTTP headers by calling setRequestHeader and getResponseHeader. The status and statusText properties yield information about the results of the call. And there are properties for retrieving the body of the response as text (responseText) or in an XML format (responseXML).

Listing 6-1 (Time.aspx) is a web page that returns the server time to its caller. It takes no parameters and returns a string. Although it’s easy to handle strings, ASP.NET makes development easier by serial-izing and deserializing more complex types that can be passed between web services and JavaScript. You will see examples of this later in this chapter when web services are used instead of invoking an ASP.NET page directly.

Listing 6-1
Image from book

<%@ Page Language="C#" %>
<script runat="server">
protected override void OnLoad(EventArgs e) {
    base.OnLoad(e);    
    Response.Write(DateTime.Now.ToUniversalTime());
}
</script> 
Image from book

Listing 6-2 (CallTime.aspx) shows basic usage of the XMLHttpRequest object to call the time web page. This is the kind of classic JavaScript code you’d find in any generic AJAX web page. You can quickly see from this code that certain pieces of JavaScript would be repeated wherever you use XMLHttpRequest. ASP.NET AJAX abstracts much of this repetitive code to simplify and streamline your code. In this example, you first determine whether or not the user is browsing with Internet Explorer by checking for ActiveX support. If not, the native XMLHttpRequest object is used. Next, call the open method with parameters to perform an HTTP GET request, the service address, and a Boolean true to indicate that the request should be asynchronous. The readyStateChangedHandler function is assigned to the readyStateChange event, and then the send method is called.

Listing 6-2
Image from book

<!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>Networking</title>
<script type="text/javascript">

var xmlhttp;

function pageLoad() {
    if(window.ActiveXObject) {
        xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
    }
    else {
        xmlhttp = new XMLHttpRequest();
    }
    xmlhttp.open("GET", "Time.aspx", true);
    xmlhttp.onreadystatechange = readyStateChangedHandler;
    xmlhttp.send();    
}

function readyStateChangedHandler() {
    if(xmlhttp.readyState == 4) {
        alert(xmlhttp.responseText);
    }    
}
</script>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager runat="server" ID="ScriptManager1">
    </asp:ScriptManager>
    <div>

    </div>
    </form>
</body>
</html>
Image from book

The readyStateChange event is fired each time the state of the XMLHttpRequest object transitions to a different phase of handling the request. The states are nonintuitively assigned fixed numbers, and 4 happens to be the state that indicates that the request has completed. Upon finding a status of 4, you display the time in an alert dialog. The code is not overly complex but does not include any error checking or do anything with the other states of the XMLHttpRequest object. As the use of the XMLHttpRequest object increases in an application, so does the complexity of the code, and the repetition of code can lead to errors and problems with maintainability. The ASP.NET AJAX WebRequest class makes leveraging the XMLHttpRequest object easier.