We’re all familiar these days with the AJAX buzz word – but while it’s relatively simple to use these browser technologies to implement a specific feature in an individual page, it is much more complex to build an entire application according to the Ajax paradigm.
Ajax pushes a new approach to programming with a lot of work being done on the client and subsequently the need for a much better organization of the code on the client side. Presentation patterns such as MVC and MVVM are gaining momentum in the JavaScript space; Separation of Concerns (SoC) is the inspiring principle of hot new Unobtrusive JavaScript methodology. Meanwhile developer’s tools for packaging, logging, unit testing, intercepting, validating JavaScript code are flourishing—even frameworks for providing forms of software contracts. Ajax contrasts with some of the well-established frameworks for Web development—specifically ASP.NET Web Forms. Not so much because you can’t do good Ajax with Web Forms, but because you’re constrained to certain forms of Ajax programming.
Especially with the advent of ASP.NET, the world of Web programming has been commoditized. Frameworks offer a thick layer of abstraction over basic HTML and HTTP interaction. And all of it works on the assumption that the browser sends an HTML form to get back an HTML page. It is relatively easy to change the paradigm for a single feature in a single page. It may be quite hard to extend the paradigm to the whole application. Why? Because the world of Ajax programming has not been commoditized. Yet.
Today, you have a lot of great tools for Ajax programming, but we are still waiting for the killer framework that makes the Ajax paradigm available to everyone. ASP.NET MVC 3 is taking steps in the right direction and so are some commercial products. Beyond that, there’s a virtually endless list of tools and libraries you have to combine together to build your ideal recipe.
This article offers a brief overview of a few aspects you might want to take into account for building successful applications.
The First Law of Ajax Development
If I have to summarize in a short sentence the essence of Ajax development I’d say “Organize your JavaScript code”. The poor, neglected JavaScript language is emerging as a surprisingly powerful language, and more and more people are changing their sentiment about the it. Like it or not, Ajax programming will be JavaScript programming. Whether you use a rich dialect such as jQuery, or write your own library, you need programming discipline to nearly the same extent as you apply to your server development. With Ajax, you are writing a share of your presentation layer with JavaScript.
Scattered JavaScript code is a thing of the past. It may still work; you may still be able to take the project home, but that’s not the way to go. And nonetheless that’s not the way to show. Get some serious JavaScript training, get a great book, search the Web, experiment—you must become a serious JavaScript developer. You can’t keep on writing Web code if you don’t know what an immediate function is or what kind of peril you’re facing by blissfully ignoring the impact of hoisting in JavaScript functions.
You need to refresh your patterns of JavaScript development, pick up your tools for logging, debugging and, yes, unit testing. A painful lesson I learned myself is that polluting the global namespace can only damage the environment. Properly applied, the Module pattern will take you to emulate namespaces which would make it simple, clean and clear to manage global variables and functions. Sure, many libraries out there offer namespaces—the Microsoft Ajax Client library being the first in line. You don’t need libraries to apply the Module pattern and it will make it so easy and safe to track the relative root URL when you have a lot of JSON calls and an application that can be hosted on the root of the site as well as a virtual application.
Unobtrusive JavaScript
An interesting corollary to the first law of Ajax development is unobtrusive JavaScript. In its simplest form, unobtrusive JavaScript couldn’t be simpler: just take out of HTML elements any attributes that refer to script code. Stop using onclick attributes on buttons and onsubmit attributes on HTML forms. Hey, wait a moment—do you realize what this means? ASP.NET Web Forms has hard-coded onclicks and onsubmits in several places. ASP.NET partial rendering is built in fully intrusive way.
Recently released, ASP.NET MVC 3 makes a point of enabling unobtrusive JavaScript in its Ajax controllers. It couldn’t be simpler—just enable a Boolean flag and the framework will do the rest. Well done, but this is simply a way to stop things from getting worse.
Unobtrusive JavaScript is a wider and deeper concept. It aims at getting a neat separation between content (HTML document), presentation (CSS style sheets) and behavior (script code). Years of ASP.NET programming taught us to build the page visually in a smart WYSIWYG editor. We bent HTML tags to any sort of use that could serve our purposes. We used TABLE for any sort of misdeed whereas the tag was created (and should be used) only to render a table of records.
A page should come back to a plain sequence of document tags—headers, P, and the excellent new tags coming up in HTML 5 such as section, footer, article. The page should be able to present its content in a readable way as plain HTML. This is content separated from everything else. Next, you add CSS and can choose different CSS styles on, say, a per-device basis. Next up, you add JavaScript. Both CSS and JavaScript should be linked in a single place and should be easy to switch them on and off. As a software developer, you probably use everyday forms of dependency injection. How is CSS and JavaScript code different from services you inject into a HTML page?
The Second Law of Ajax Development
With Ajax, the client code gains the ability to bypass the browser and can handle the connection itself. Which HTTP endpoints should Ajax clients call? They can’t certainly be the same HTTP endpoints you would call via the browser’s address bar or page links. Here’s the second law of Ajax development: give your applications an Ajax specific service layer.
In software architecture, the Service Layer pattern is defined as “a layer of services that establishes a set of available operations and coordinates the application's response in each operation.” The definition is adapted from Martin Fowler’s excellent book “Patterns of Enterprise Application Architecture.” The service layer is the next stop on the way to the back end of an application after a user action.
In an Ajax context, the service layer is a collection of HTTP endpoints that Ajax clients will call. It contains URLs callable from clicks and taps of the end user. An Ajax request doesn’t likely need an entire HTML page; it probably wants just a bunch of data, presumably XML or JSON. You need to have these endpoints readymade in a well done Ajax application.
The Third Law of Ajax Development
Most of the time, these endpoints are under your direct control as they configure as the application layer of your system. Sometimes, however, the Ajax presentation layer needs to call into external, cross-domain endpoints. Cross-domain calls are not supported by browsers regardless of what the servers actually hosting the endpoints may think.
JSONP is an approach that today represents the best possible compromise between Ajax calls and cross-domain sites. The W3C has something in the works to make legal, authorized cross-domain calls seamless. The W3C released a working draft of a protocol known as Cross-Origin Resource Sharing (CORS) according to which clients place a request with a particular header and server reply with an ad hoc response header. Lacking the response header, browsers should refuse the response. This behavior is expected to be incorporated into the XMLHttpRequest object. To be precise, most browsers already implement this with the notable exception of Internet Explorer, including upcoming version 9. IE does have its own solution for cross-domain calls but it is based on a proprietary object. Waiting for CORS to become a standard, JSONP or JSON with Padding is today the most reliable and common way to implement cross-domain calls for sites that support the protocol.
In addition to location, HTTP endpoints for Ajax calls may also implement long-running tasks. Typically, you might want to be able to monitor and perhaps interrupt these tasks if they hang. You will learn on your own that no standard exist for this and not even frameworks. The reason is that the problem is open and solutions seem to be constrained to a project. However, if the endpoint is aware of being long-running and therefore monitorable and interruptible, something can be done with a bit of creativity and infrastructure. For example, you can identify each long-running Ajax task with a GUID and spawn a parallel timer that periodically checks the status of the task using the GUID. This requires you have a server-side persistent infrastructure where the running task saves its state that polling services can read.
Remember me on this computer
For functions that are available only to authenticated users a cookie is created at the successful completion of the authentication process. The cookie has its own expiration and for the duration of it the user is allowed to access protected pages without having to retype credentials. If the cookie expires, on the next access the user will be automatically redirected to the login page and gently asked to reenter user name and password.
This pattern may get you problems in an Ajax scenario. Your page places an Ajax call and the server detects that the authentication cookie has expired. The server returns a HTTP 302 status which redirects the user to the login page. However, in an Ajax scenario it’s the XMLHttpRequest object—not the browser—that handles the request. XMLHttpRequest correctly handles the redirect and goes to the login page. Unfortunately, the original issuer of the Ajax call will get back the markup of the login page instead of the expected bunch of data. As a result, the login page will likely be inserted in any DOM location where the original response was expected.
There are a couple of approaches you can take to solve the problem. One consists in intercepting the authentication phase of the request and checking whether the ongoing request is an Ajax request. The other consists in adding code to the actual login page to detect the Ajax call and return only a compatible chunk of HTML.
Summary
Writing Ajax applications is not the picnic that the availability of powerful and rich libraries and framework may suggest. Writing Ajax applications is hard because we have tools but not common and consolidated strategies. Quite clearly, it’s the ASP.NET paradigm that is on a dead track and we are trying to develop practices that one day someone will incorporate into a new super framework. When this happens it will be the beginning of the era of commoditization for Ajax development.
Comments