October 2009

Volume 24 Number 10

Cutting Edge - Data Binding in ASP.NET AJAX 4.0

By Dino Esposito | October 2009

Stop beating around the bush: AJAX is possible only with a strong JavaScript engine that runs within the client browser and provides the foundation for more advanced and asynchronous features. The JavaScript library currently incorporated in ASP.NET 3.5 Service Pack 1 is a necessary, but insufficient, attempt to deliver such a library. A more powerful ASP.NET AJAX platform is required, and it is just being introduced as part of ASP.NET AJAX 4.0.

Abstractly speaking, an AJAX-based front-end is a presentation layer that combines rich UI capabilities with the implementation of some application logic. The application logic is essentially the code behind all the use-case diagrams that resulted from the design and analysis phases. The application logic expresses the intended behavior of the application and how a user is expected to interact with the whole system.

What makes an AJAX front-end fairly unique, at least when compared to a classic Web or smart-client front-end, is the pressing need to mix elements of a rich user experience with low-level programming tools. Because an AJAX front-end runs within the client browser, it can rely only on HTML to produce the user interface and only on JavaScript to spice up the visual elements with special effects, drag-and-drop, asynchronous data fetch and partial updates.

To meet expectations, a modern and effective AJAX platform must provide two key capabilities. First, it must enable developers to place asynchronous calls to a HTTP façade of ad hoc server modules. Second, it must enable developers to incorporate any received raw data into the existing page Document Object Model (DOM). Both capabilities, though, would lose much of their inherent appeal if implemented in a way that isn't that easy and effective.

In ASP.NET 3.5 Service Pack 1, developers find a powerful and reliable API to connect asynchronously to a layer of HTTP-based Web services. ASP.NET AJAX 3.5 makes it possible, and easy overall, for you to reference a Web service from the client page. When you do so, the framework also automatically generates a JavaScript proxy class that mirrors the service contract. The existing AJAX framework, both on the server and client, works to shield developers from all details of data serialization. From the perspective of the JavaScript developer, a remote Web service (still subject to the well-known same-origin policy) is like a local JavaScript object exposing behavior through methods.

ASP.NET 3.5 Service Pack 1 doesn't offer the same virtues as far as the building of the user interface is concerned. It makes it very easy to fetch raw data from the server, but it doesn't offer much in the way of a powerful interface to display this raw data in a user interface. The major weakness of the AJAX support in ASP.NET 3.5 Service Pack 1 is the lack of effective tools for client-side data binding and HTML templates. That is why an engine for client-side template rendering and a made-to-measure data binding syntax are the most compelling features you find in ASP.NET AJAX 4.0.

In this article, I'll review the pillars of real-world AJAX development as supported in ASP.NET AJAX 4.0. In doing so, I'll mostly focus on client-side templates and data binding but won't ignore other goodies, such as ADO.NET Data Services proxy classes and programming facilities.

Pillars of Real-World AJAX Development

Real-world AJAX development is about building rich user interfaces over the Web, and it requires the application of new design patterns and employment of new programming tools.

For a long time, any Web user interface represented a whole step backward in terms of usability and responsiveness if compared to any desktop user interface. For a long time, Web developers just ignored (because it was not relevant to their work) a number of UI patterns and programming features, including predictive fetch, caching, monitoring of remote tasks, context-sensitive and drill-down display, subviews, partial UI disablement, and modality.

In classic Web development, the building of the user interface was entirely delegated to the server side and effectively implemented using server-side data binding and ad hoc controls. The advent of the AJAX paradigm made this mode obsolete and unappealing for increasing numbers of applications.

Data binding, though, is too powerful a feature to overlook in an AJAX programming model. Also, object-orientation is hard to refuse when the complexity of code grows beyond a given threshold. At the same time, a Web application remains a pretty unique combination of small footprints, cacheable downloads and rich capabilities.

On the way to real-world AJAX development, JavaScript libraries are the only affordable way to add programming power. Through JavaScript libraries, you provide the foundation of object-orientation in a non-OOP language; you offer rich and off-the-shelf UI widgets; and you can offer programming tools to effectively code data binding entirely on the client-side.

Without a powerful model for client-side data binding, you can't have a powerful platform for real-world AJAX development.

Requirements for Client-Side Data Binding

There are two fundamental patterns for implementing data binding functionalities. One is the HTML Message pattern, and the other is the Browser-side Template pattern. The former entails making a remote service call to a component that returns prearranged HTML markup ready for display. The latter is all about setting up machinery to download raw data and decide on the client how to render it out.

The HTML Message pattern is similar to a smart form of partial rendering, except that it doesn't involve any view state and can be configured to be an autonomous operation not bound to any other postback operations occurring in the same application. In an implementation of the HTML Message pattern, everything takes place on the server; any data binding is essentially a form of classic server-side data binding involving controls such as DataGrid and ListView and managed containers of fetched data.

The HTML Message pattern can be easily implemented with the tools available in ASP.NET 3.5. All that it requires on the client is the binding of returned markup to the page DOM. The code snippet below shows what's really required from a coding perspective:

grid.innerHTML = markup;

In the example, grid indicates the HTML element to contain the markup—typically this is a DIV tag. The variable named markup, on the other hand, indicates any chunk of HTML obtained as a response from a service method call.

It goes without saying that the service used to implement the HTML Message pattern must incorporate both the logic to retrieve or calculate the data to return, plus any logic required to format the data to HTML.

In general, a solution based on the HTML Message pattern requires more bandwidth as the average size of the response for each remote method call increases.

The Browser-side Template pattern (BST) requires more coding on your side but can also deliver better results both in terms of flexibility and bandwidth optimization. The BST pattern is based on the idea that you place a remote call to retrieve data. Data is then downloaded on the client in a format that allows manipulation with JavaScript. Finally, data is merged with the existing page DOM and produces any complex interface you need.

Too often, the power of the AJAX paradigm is mistakenly represented with the possibility of asynchronously updating small portions of the user interface. It is one thing to get a scalar value asynchronously (say, the current balance of a bank account) and insert that into the existing page DOM; it is quite another thing to refresh asynchronously an array of data that changes frequently and requires a gridlike infrastructure to display.

The server side is simple with server controls, as below:

Collection<StockInfo> stocks = GetLatestQuotes(...);
DataGrid1.DataSource = stocks;
DataGrid1.DataBind();

What would be the equivalent of such code for the client side? The first part can be easily mapped to the features of ASP.NET 3.5. All you do is instantiate and use a client proxy for a remote service that is capable of getting you up-to-date values, like so:

var service = new Samples.Services.FinanceService();
var stocks = service.GetLatestQuotes(...);

The stocks variable is a JavaScript array of objects that represents the data you received. How would you fit this chunk of raw data into an existing HTML layout? The BST pattern is here to help. It requires that you define the following elements: your own syntax for HTML templates and related data placeholders; your own syntax for binding actual data to placeholders; an HTML factory that takes templates and data and produces updated markup; and glue code to tie it up all together while offering a manageable programming interface.

ASP.NET AJAX 4.0 provides an implementation of the BST pattern out of the box. The scaffolding for ASP.NET AJAX templates is defined in the MicrosoftAjaxTemplates.js file. You need to reference this file via the ScriptManager control (or ScriptManagerProxy if you use master pages). If you use ASP.NET MVC or prefer to reference script files via the traditional <script> tag, then you must also add a preliminary reference to MicrosoftAjax.js.

Syntax for HTML Templates

Years of ASP.NET programming have proven beyond any reasonable doubt that HTML templates are an excellent way to create a Web user interface from data. An HTML template is a piece of HTML that contains literals, ASP.NET controls and placeholders for binding data. Bound to raw data and processed by an ad hoc engine, an HTML template morphs into plain HTML for the browser to render. A template exists to bind data and originate a chunk of markup to display; until binding occurs, the template is hidden from view.

In spite of a relatively simple description, an HTML template is quite difficult to implement in a real-world AJAX framework. A few attempts have been made by popular libraries, such as Prototype JS, to formalize an HTML template. While there's common agreement on the features one should expect from an HTML template, a common model for defining an HTML template in a browser doesn't exist yet.

A template must be able to render XHTML-compliant markup. A template must be processed as quickly as possible by the underlying rendering engine and should let the engine render a large percentage of the markup before the user realizes there's a delayed response from the application. A template must support a very simple syntax for binding that is easy to read, while not being limited to simple cases only. You should be able to mix markup and code in a template. Ideally, the code that triggers the rendering of the template should be declarative and not particularly intrusive.

Let's review the characteristics of the HTML template model supported by ASP.NET AJAX 4.0.

In ASP.NET AJAX 4.0, an HTML template is a DIV tag, or any other container tag, decorated with the sys-template class attribute, as shown below:

<div>
<ul id="MyItem" class="sys-template">
       <li>
         {{ Symbol }}, {{ Quote }}, {{ Change }}
       </li>
</ul>
</div>

The sys-template CSS class is a convention that marks the element, and its content, as initially invisible. Note that the sys-template must be defined explicitly in the master page, or in every page, as follows:

<style type="text/css">
.sys-template { display:none; visibility:hidden; }
</style>

When rendered, a template is given a data context and the body of the template can host bindings to public fields and properties of the data context object. Likewise, any elements in the template can reference any JavaScript expression that evaluates to a string.

Syntax for Data Bindings

The syntax to express a binding between a placeholder in the template and external data is as follows:

{{ expression }}

As mentioned, the expression can be the name of a public member of the data context object or a JavaScript expression that returns a string. Such expressions can appear anywhere in the template and can also be used to assign a value to an attribute, as shown below:

<div>
  <ul id="MyItem" class="sys-template">
     <li>
       <asp:Label runat="server"
            Text="{{CompanyName}}" />
     </li>
  </ul>
</div>

An HTML template doesn't have to be made of plain HTML literals; you can use ASP.NET markup as well. Given the preceding code snippet, here's the markup emitted by the Label control:

<span>{{ CompanyName }}</span>

As you can see, the use of a server control in the source code of the page doesn't hinder client-side rendering of templates.

Client events can be defined within a template using the familiar onXXX syntax or via the $addHandler function in the Microsoft AJAX Library. 

DataView Control and Template Instantiation

To display data, a template must be instantiated, bound to data and rendered within a container. The Sys.UI.DataView client control can be used to automate and simplify all these tasks.

The DataView control is essentially a component that takes some input data and the ASP.NET AJAX template and produces HTML markup to be displayed within the page. The DataView is also referenced as a behavior component. In general, a behavior is a script-based component that, once attached to a DOM element, changes the way in which the HTML element works within the client browser. You can work with a behavior in either of two ways. You can declaratively attach the behavior to its target DOM element, or you can create an instance of the behavior and configure it programmatically. In the latter case, the association between the behavior and the template is just part of the configuration. Let's tackle the declarative approach first.

Before I go any further, though, let me clarify that the DataView is just one possible behavior component. Anything you read later on regarding declarative instantiation and attachment applies to any behavior you may run across in ASP.NET AJAX.


Figure 1 The DataView Behavior in Action

Attaching Behaviors Declaratively

To attach behaviors to a DOM element, you use the sys:attach custom attribute. As you can see, the attribute is associated with a namespace URI that makes it XHTML compliant. You declare the sys prefix in the <body> element:

<body xmlns:sys="javascript:Sys" ...>

The sys prefix maps to the javascript:Sys namespace URI defined in the Microsoft AJAX library. Using the sys:attach attribute serves only the purpose of establishing an association between an existing behavior and an HTML element. You still need to instantiate the behavior component. You do that by defining another custom namespaced attribute in the <body> element. The value of the attribute will reference the JavaScript object to instantiate:

<body xmlns:sys="javascript:Sys"
      xmlns:dataview="javascript:Sys.UI.DataView" ...>

The name of the attribute—dataview, in the preceding code snippet—is arbitrary and can be changed to anything else you like. Whatever name you pick, however, it must be maintained in the remainder of the code to reference the behavior.

The effective instantiation of any attached script behavior occurs when the page is loaded and the DOM element gets processed. The browser that is loading the page may not know anything about how to handle such library-defined behaviors. The ASP.NET AJAX framework is ultimately responsible for the instantiation of its own behaviors. However, the ASP.NET AJAX framework requires ad hoc instructions from you to proceed. In particular, you want the framework to kick in during the DOM parsing process and have it look in the content of any parsed element to take care of any sys:attach attributes.

Figure 2 Controlling a DataView Object Programmatically

<script type="text/javascript">

// Define a global instance of the DataView
var theDataView = null;

// This function can be called from anywhere in the page to
// fill the template with passed data and update the page.
function renderTemplate(dataSource) 
{
    // Ensure we have just one copy of the DataView.
    // The DataView's constructor gets a DOM reference to the template.
    if (theDataView === null)
        theDataView = new Sys.UI.DataView($get("MyTemplate"));

    // Bind data to the template associated with the DataView
    theDataView.set_data(dataSource);

    // Force the template to render 
    theDataView.refresh();
}

</script>

For performance reasons, the ASP.NET AJAX framework is not designed to automatically take care of any DOM element the browser encounters along the way. It is therefore up to you to explicitly indicate which DOM elements need to be scanned for attached behaviors that support declarative instantiation. You enable a DOM element to contain declaratively instantiated behaviors by using the sys:activate attribute. You use the attribute in the <body> element and set it to a comma-separated list of element IDs:

<body xmlns:sys="javascript:Sys"
      xmlns:dataview="javascript:Sys.UI.DataView"
      sys:activate="customerList">

The preceding code instructs the framework to automatically instantiate any behavior that may be attached to the customerList DOM element.

You can also use the wildcard symbol (*) if you want to activate the whole document. Use this option with care, especially on large pages because it may introduce a rendering delay. With the DataView behavior fully configured in the <body> element, all that remains to do is to bind fresh data to the template: 

<div id="customerList">
    <ul class="sys-template"
        sys:attach="dataview"
        dataview:data="{{ theCustomers }}">
        <li>
            <span ><b>{{ ID }}</b></span>
            <asp:label runat="server"
                 Text="{{ CompanyName }}"></asp:label>
        </li>
    </ul>
</div>

The DataView component has a rich programming interface that, among other things, includes a data property. The data property represents the data context for the bound template. You can set the data property both declaratively and programmatically. In the code snippet below, the data property is declaratively set to the content of a global array named theCustomers:

<ul class="sys-template"
    sys:attach="dataview"
    dataview:data="{{ theCustomers }}">
...
</ul>

In general, you can set the data property to any JavaScript expression that evaluates to a bindable object or an array of objects. You opt for a declarative approach when you intend to bind the template to some global data.

The code download sample titled A Sample Page Using Declarative Binding shows the full listing of a sample page. Figure 1 shows the sample page in action.

For programmatic binding, you need to obtain a reference to the DataView object and call the setter method of the data property. You retrieve the DataView instance via the $find helper defined in the Microsoft AJAX library. The ID of the DataView component matches the ID of the DOM element it is attached to. Consider the following code snippet:

<ul class="sys-template"
    sys:attach="dataview"
    id="DataView1">
...
</ul>
<input type="button"
       value="Perform binding"
       onclick="bind()" />

You can perform the data binding only when the user explicitly clicks the button. Here's the code you need to put in the bind JavaScript function:

<script type="text/javascript">
    function bind() {
        theDataView = $find("DataView1");
        theDataView.set_data(theCustomers);
    }
</script>

You first retrieve the DataView instance by ID and then assign new content to its data property.

Tips for Master Pages

When you use a master page, you usually leave the <body> tag of the page template in the master. It is then necessary that you edit the master page to attach any required behavior. Alternatively, you can put the <body> tag in a content placeholder and force developers to set it explicitly in any content page.

The <body> tag is required to register attachable behaviors, such as DataView, and to enable DOM elements to recognize and instantiate behaviors through the sys:activate attribute.

It should be noted that an alternative exists to editing the <body> tag. You can use the new ClientElementsToActivate property on the ScriptManager control, as follows:

<asp:ScriptManager runat="server"
                   ID="ScriptManagerProxy1"
                   ClientElementsToActivate="*">
    <Scripts>
        <asp:ScriptReference Name="MicrosoftAjaxTemplates.js" />           
    </Scripts>
    ...
</asp:ScriptManager>

 Note that only a few of the properties defined on the ScriptManager control are mirrored on the ScriptManagerProxy control, which is the wrapper control you use to replicate ScriptManager functionality in a content page. In ASP.NET 4.0, however, the ClientElementsToActivate is among the few properties you can access on both controls.

You might be wondering how a string array property like ClientElementsToActivate can affect the behavior of a JavaScript framework, such as the ASP.NET AJAX framework. When the ClientElementsToActivate property is set, the script manager control emits an extra line of script within the page that adds one or more entries to an internal array on the Sys.Application object in the Microsoft AJAX Library. 

Using the DataView Control Programmatically

So far, we've examined a scenario in which the HTML template is attached to a DataView behavior for mixing together layout and data into fresh HTML. This is not the only possible approach to client-side data binding. 

You can also create an instance of the DataView component programmatically and pass the template to it to use as an argument. Figure 2 provides a brief but illustrative listing.

The constructor of the DataView takes a DOM reference to the template to use internally. The setter method of the data property gets fresh data to bind. Finally, the refresh method forces an update of the HTML template that displays freshly bound data.

To create an instance of the DataView, you can also resort to the $create helper method, as shown below:

<script type="text/javascript">
function pageLoad() {
$create(
       Sys.UI.DataView,
       {},
       {},
       {},
       $get("MyTemplate")
);
}
</script>

A very common scenario in which using a DataView definitely smoothes your programming efforts is to populate a complex HTML template with data provided by a remote Web service. Let's investigate this point further.

Fetching Data from Web Services

The programming interface of the DataView component features a number of members specifically designed to serve the scenario in which the content of the DataView comes from a remote URI. The download includes a list of members of the DataView that work with Web Services.

Note that the content of the code download sample titled An Auto-Fetch DataView to Consume Data from a Remote URI doesn't fully comprehend the entire API of the DataView component. Many more members exist to serve other scenarios that I'll cover in depth in a future column.

The code download sample titled An Auto-Fetch DataView to Consume Data from a Remote URI shows the JavaScript code that creates a DataView when the page loads. The DataView is configured to fetch its data immediately by placing a call to the specified Web service method.

The dataProvider property indicates the data source, whereas the fetchOperation sets the method to invoke. Finally, fetchParameters is an dictionary object that contains parameter information for the method. You set it to a JavaScript object where each property matches the name of a formal parameter on the method definition. In particular, in the previous example, the method GetQuotesFromConfig has the following prototype:

[OperationContract(Name="GetQuotesFromConfig")]
StockInfo[] GetQuotes(bool isOffline);

The DataView receives the HTML template to populate via the $create helper function and once data has been successfully fetched, it fills up any placeholders in the template.


Figure 3 A Rich Data-Bound Web Page Using AJAX and jQuery

The sample code also contains a custom timer object that periodically refreshes the template with a bit of jQuery animation. When the timer ticks, a new fetch operation is ordered using any current value for the "offline" checkbox. The "offline" checkbox indicates whether the Web service is expected to return fake stocks and values or connect to a real-world finance service to grab quotes for true stocks. The service gets the URL of the finance service and the list of stocks from the configuration file. (See the source code for details.)

Next Month

Figure 3 shows a rich and animated data-bound ASP.NET AJAX page that uses client-side rendering to bind raw data to a relatively complex HTML template. In ASP.NET AJAX 4.0, you find powerful programming tools to make coding such pages no more difficult than doing traditional server-side data binding.

The page shown in Figure 3 is only the first, and the simplest, step of a longer path. Next month, I'll discuss more features of rich templates and how to put logic in HTML templates, and I'll explore live data binding. Stay tuned!           


Dino Esposito is an architect at IDesign and the co-author of "Microsoft .NET: Architecting Applications for the Enterprise" (Microsoft Press, 2008). Based in Italy, Esposito is a frequent speaker at industry events worldwide. You can join his blog at weblogs.asp.net/despos.