Sie sind auf Seite 1von 64

Looking Ahead to ASP.NET 4.

0
K. Scott Allen
When Visual Studio 2010 and .NET 4.0 arrive next year, we ASP.NET developers will have two mature
frameworks for building Web applications: the ASP.NET Web Forms framework and the ASP.NET MVC
framework. Both build on top of the core ASP.NET runtime, and both are getting some new features to start the next
decade.
I dont have the space to cover every addition to ASP.NET in one article, as there are numerous improvements to
both frameworks and the underlying runtime. Instead, Ill highlight what I think are the important new features for
Web Forms and MVC.
New For ASP.NET Web Forms
ASP.NET Web Forms will be over eight years old by the time Microsoft releases Version 4, and the team continues
to refine the framework and make improvements. In my last column, I touched on a few of these improvements, like
the new classes that make it easy to use the URL routing features now included in the core services of ASP.NET,
and the new MetaKeywords and MetaDescription properties on the Page base class that make it simple to control the
content of metatags on a form. These changes are relatively minor, however.
The key changes in Web Forms address some of the chief criticisms about the framework. Many developers have
wanted more control over the HTML a Web form and its controls produce, including the client-side identifiers
emitted inside the HTML. In 4.0, many of ASP.NETs server-side controls were reworked to produce HTML that is
easier to style with CSS and conforms to conventional Web practices. Also, new properties have been added to base
classes that will give developers more control over the client-side identifiers generated by the framework. Ill
highlight these changes in the following sections.
CSS-Friendly HTML
One example of a server control that is notoriously difficult to style with CSS is the ASP.NET menu control. When
the menu renders, it emits nested table tags that include cellpadding, cellspacing and border attributes. To make
matters worse, the menu control embeds style information inside the cells of the nested tables and injects an in-line
style block at the top of the page. As an example, look at the following definition of a simple menu:
<asp:Menu runat="server" ID="_menu">
<Items>
<asp:MenuItem Text="Home" NavigateUrl="~/Default.aspx" />
<asp:MenuItem Text="Shop" NavigateUrl="~/Shop.aspx" />
</Items>
</asp:Menu>
In ASP.NET 3.5, the simple menu produces the following HTML (with some attributes omitted or shortened for
clarity):
<table class="..." cellpadding="0" cellspacing="0" border="0">
<tr id="_menun0">
<td>
<table cellpadding="0" cellspacing="0"
border="0" width="100%">
<tr>
<td style="...">
<a class="..." href="Default.aspx">Home</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
In ASP.NET 4.0, Microsoft revised the menu control to produce semantic markup. The same menu control in
ASP.NET 4.0 will produce the following HTML:
<div id="_menu">
<ul class="level1">
<li><a class="level1" href="Default.aspx" target="">Home</a></li>
</ul>
</div>
This type of CSS-friendly markup was achievable in previous versions of ASP.NET if you used a control adapter to
provide alternate rendering logic for a control, but now the markup is CSS-friendly by default. If you already have
style sheets and client script written against the HTML produced by ASP.NET 3.5, you can set the
controlRenderingCompatibilityVersion attribute of the pages section in web.config to the value 3.5, and the
control will produce the nested table markup we saw earlier. The default value for this attribute is 4.0. Note that the
4.0 menu control still produces a style block at the top of the page, but you turn this off by setting the
IncludeStyleBlock property of the control to false.
Many other controls in 4.0 are CSS-friendly as well. For example, validation controls like the RangeValidator and
RequiredFieldValidator will no longer render inline styles, and template controls like the FormView, Login, and
Wizard control will no longer render themselves inside of a table tag (but only if you set the RenderOuterTable
property on these controls to false). Other controls have changed, too. As just one example, you can force the
RadioButtonList and CheckBoxList controls to render their inputs inside of list elements by setting the
RepeatLayout property to the value OrderedList or UnorderedList, which forces the controls to render using ol and li
elements, respectively.
Generating Client IDs
If you have ever written client-side script to manipulate the DOM, then you are probably aware of ASP.NETs
affinity for changing client-side ID attributes. In an effort to ensure that all ID attributes are unique on a page,
ASP.NET will generate a client ID by concatenating a controls ID property with additional information. On the
server, you can access the generated value using the ClientID property of a control.
As an example, if a control is inside a naming container (a control that implements the INamingContainer interface,
as user controls and master pages do), then ASP.NET produces the ClientID value by prefixing the naming
containers ID to the controls ID. For data-bound controls that render repeating blocks of HTML, ASP.NET will
add a prefix that includes sequential numbers. If you view the source of any ASP.NET page, youll probably
encounter id values like ctl00_content_ctl20_ctl00_loginlink. These generated values add an extra level of
difficulty when writing client script for a Web Forms page.
In Web Forms 4.0, a new ClientIDMode property is on every control. You can use this property to influence the
algorithm ASP.NET will use for generating the controls ClientID value. Setting the value to Static tells ASP.NET
to use the controls ID as its ClientID, with no concatenation or prefixing. For example, the CheckBoxList in the
following code will generate an <ol> tag with a client id of checklist, regardless of where the control exists on the
page:
<asp:CheckBoxList runat="server" RepeatLayout="OrderedList"
ID="checklist" ClientIDMode="Static">
<asp:ListItem>Candy</asp:ListItem>
<asp:ListItem>Flowers</asp:ListItem>
</asp:CheckBoxList>
When using a ClientIDMode of Static, youll need to ensure the client identifiers are unique. If duplicated id values
exist on a page, youll effectively break any scripts that are searching for DOM elements by their ID value.
There are three additional values available for the ClientIDMode property. The value Predictable is useful for
controls implementing IDataBoundListControl, like the GridView and ListView. Use the Predictable value in
conjunction with the ClientIDRowSuffix property of these controls to generate client IDs with specific values
suffixed to the end of the ID. For example, the following ListView will bind to a list of Employee objects. Each
object has EmployeeID and IsSalaried properties. The combination of the ClientIDMode and ClientIDRowSuffix
properties tell the CheckBox to generate a client ID like employeeList_IsSalaried_10, where 10 represents the
associated employees ID.
<asp:ListView runat="server" ID="employeeList"
ClientIDMode="Predictable"
ClientIDRowSuffix="EmployeeID">
<ItemTemplate>
<asp:CheckBox runat="server" ID="IsSalaried"
Checked=<%# Eval("IsSalaried") %> />
</ItemTemplate>
</asp:ListView>
Another possible value for ClientIDMode is Inherit. All controls on a page use a ClientIDMode of Inherit by default.
Inherit means the control will use the same ClientIDMode as its parent. In the previous code sample, the CheckBox
inherits its ClientIDMode value from the ListView, which holds the value Predictable. The final possible value for
ClientIDMode is AutoID. AutoID tells ASP.NET to use the same algorithm for generating the ClientID property as
it does in Version 3.5. The default value for a pages ClientIDMode property is AutoID. Since all controls on a page
default to using a ClientIDMode of Inherit, moving an existing ASP.NET application to 4.0 will not change the
algorithm the runtime uses to generate client ID values until you make a change to a ClientIDMode property. This
property can also be set in the pages section of web.config to provide a different default for all pages in an
application.
New Project Template
The Web application and Web site project templates in Visual Studio 2008 provide a Default.aspx page, a
web.config file and an App_Data folder. These starting templates are simple and require some additional work
before you can get started on a real application. The same templates in Visual Studio 2010 provide more of the
infrastructure you need to build an application using contemporary practices. A screen capture of a brand new
application produced by these templates is shown in Figure 1.

Figure 1 New Web Application in Visual Studio 2010
Notice how the new application includes a master page by default (Site.master). All of the .aspx files you find inside
the new project will be content pages using ContentPlaceholder controls to plug content into the structure defined by
the master page. Notice the new project also includes a style sheet in the Content directory (Site.css). The master
page includes this style sheet using a link tag, and inside the style sheet youll find a number of styles defined to
control the appearance of the page body, headings, primary layout and more. The new project also includes a Scripts
directory with the latest version of the jQuery library, an open source JavaScript framework officially supported by
Microsoft and included with Visual Studio 2010 as part of the install.
The new project template, with its use of master pages and style sheets, will help developers get started in the right
direction when using Web Forms. A running version of the new application is shown in Figure 2. Visual Studio
2010 will also include Empty templates for both Web sites and Web applications. These empty templates will not
include files or directories when you use them, so youll be starting your application from scratch.

Figure 2 Running the new ASP.NET Application
Another bit of good news about new projects in ASP.NET 4.0 is that the web.config file starts off nearly empty.
Most of the configuration we became accustomed to seeing in ASP.NET 3.5 web.config files is now in the
machine.config file that lives underneath the 4.0 frameworks installation directory. This includes the configuration
of controls from the System.Web.Extensions directory, the HTTP handlers and modules configured to support
JavaScript proxies for Web services, and the system.webserver section for Web sites running under IIS 7.
New for ASP.NET MVC
Visual Studio 2010 should bring us the second release of the ASP.NET MVC framework. While still young, the
framework has attracted many Web developers who wanted a framework designed for testability. The second
release of ASP.NET MVC is going to focus on better developer productivity and adding the infrastructure to handle
large, enterprise-scale projects.
Areas
One approach to building an extremely large ASP.NET Web Forms application is to break apart the application into
multiple sub-projects (an approach promoted by the P&P Web Client Composite Library). This approach is difficult
to undertake with ASP.NET MVC 1.0 because it works against a number of the MVC conventions. MVC 2.0 will
officially support this scenario using the concept of an area. An area allows you to partition an MVC application
across Web application projects, or across directories inside of a single project. Areas help to separate logically
different pieces of the same application for better maintainability.
The parent area of an MVC Web application is an MVC project that will include a global.asax and root level
web.config file for the application. The parent area can also include common pieces of content, like application-wide
style sheets, JavaScript libraries, and master pages. Child areas are also MVC Web application projects, but since
these projects physically exist underneath the parent area project at runtime, the parent and its children will appear
as a single application.
As an example, imagine a large inventory application. In addition to the parent area, the inventory application might
be broken into ordering, distributing, reporting and administrative areas. Each area can live in a separate MVC web
project, and each project will need to register its routes by including a class that derives from the abstract base class
AreaRegistration. In the code that follows, we override the AreaName property to return the friendly name of the
reporting area, and override the RegisterArea method to define the routes available in the reporting area:
public class ReportingAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "Reporting"; }
}

public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
// route name
"ReportingDefault",
// url pattern
"reporting/{controller}/{action}",
// route defaults
new { controller = "Home", action = "Index" },
// namespaces
new string[] { "Reporting.Controllers" });
}
}
Notice that we include a string array of namespaces to search when locating the controller for the reporting area.
Constraining the namespaces to search allows different areas to have controllers with the same name (multiple
HomeController classes can exist in the application, for example).
DataAnnotations for Easy Validation
The DefaultModelBinder in ASP.NET MVC is responsible for moving data from the request environment into
model properties. For example, when the model binder sees a model object with a property named Title, it will look
through the form, query string and server variables to find a variable with a matching name (Title). However, the
model binder doesnt perform any validation checks beyond simple type conversions. If you want the Title property
of your model object to contain only strings with 50 characters or less, you have to perform this validation check
during the execution of your controller action, implement a custom model binder or implement the IDataErrorInfo
interface on your model.
In ASP.NET MVC 2.0, the DefaultModelBinder will look at DataAnnotation attributes on model objects. These
DataAnnotation attributes allow you to provide validation constraints on your model. As an example, consider the
following Movie class:
public class Movie
{
[Required(ErrorMessage="The movie must have a title.")]
[StringLength(50, ErrorMessage="The movie title is too long.")]
public string Title { get; set; }
}
The attributes on the Title property tell the model binder that the Title is a required field, and the maximum length of
the string is 50 characters. The MVC framework can automatically display the ErrorMessage text in the browser
when validation fails. Additional built-in validation attributes include an attribute to check a range and an attribute
to match a regular expression.
At the time of this writing, the MVC runtime uses only the validation attributes for server-side validation checks.
The MVC team expects to generate client-side validation logic from the validation attributes by the time it releases
MVC 2.0. Driving both the server- and client-side validation using these attributes will be a boon for the
maintainability of an application.
Templated Helpers
Templated helpers in ASP.NET MVC 2.0 also consume DataAnnotation attributes. But instead of using the
attributes to drive validation logic, template helpers use the attributes to drive the UI display of a model. The
template helpers begin with the new HTML helper methods DisplayFor and EditorFor. These helper methods will
locate the templates for a given model based on the models type. For example, lets use the Movie class we looked
at before, but with an additional property:
public class Movie
{
// ...

[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
}
In this scenario, every movie carries its release date, but no one ever cares what time of day a movie is released. We
only want to display the date information when displaying this property, and not the time information. Notice the
property is decorated with a DataType attribute that advertises our intention.
To properly display the release date, we need a display template. A display template is just a partial view with an
.ascx extension that lives inside a DisplayTemplates folder. The DisplayTemplates folder itself can live underneath a
controllers view folder (in which case the template applies only to the views for that one controller), or in the
shared views folder (in which case the template is available everywhere). In this case, the template needs the name
Date.ascx and looks like the following:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%= Html.Encode(String.Format("{0:d}", Model)) %>
In order for the MVC framework to use this template, we need to use the DisplayFor helper method when rendering
the ReleaseDate property. The code shown in Figure 3 is from another template, the Movie.ascx display template.
Figure 3 Movie.ascx Display Template
<%@ Control Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<Movie>" %>

<fieldset>
<legend>Fields</legend>
<p>
Title:
<%= Html.LabelFor(m => m.Title) %>
<%= Html.DisplayFor(m => m.Title) %>
</p>
<p>
<%= Html.LabelFor(m => m.ReleaseDate) %>
<%= Html.DisplayFor(m => m.ReleaseDate) %>
</p>
</fieldset>
Notice how the LabelFor and DisplayFor helper methods are strongly typed, which can help you propagate changes
if a model is refactored. To use the Movie.ascx template to display a movie anywhere in an application, we just need
to use the DisplayFor helper again. The following code is from a view that is strongly typed against the Movie class:
<asp:Content ID="detailContent"
ContentPlaceHolderID="MainContent"
runat="server">
Movie:
<%= Html.DisplayFor(m => m) %>

</p>
</asp:Content>
The DisplayFor method is strongly typed to use the same model as the view page, so the m parameter in the
DisplayFor lambda expression is of type Movie. DisplayFor will automatically use the Movie.ascx template when
displaying the movie (which in turn uses a DisplayFor to find the Date.ascx template). If we did not use the
DataType attribute on the ReleaseDate property of a movie, DisplayFor would not use the Date.ascx template and
would display the date and the time portions of the ReleaseDate, but the DataType attribute helps guide the
framework to the correct template. This concept of strongly typed, nested templates and data type annotations is
powerful and will prove to be a productivity boost.

Exploring ASP.NET 4.0Web Forms
and Beyond
Dino Esposito
ASP.NET is a stable and mature platform for building rich and powerful Web applications, so it's hard to imagine a
new set of compelling features being added to it. But last fall, with the release of Service Pack 1 for ASP.NET 3.5,
Microsoft refined the platform's built-in AJAX support and enhanced its productivity by shipping Dynamic Data
controls, a new framework of components specifically designed to address the needs of data-driven and data-entry
applications.
In parallel, Microsoft developed a brand-new, alternative programming model called ASP.NET MVC. Unlike the
classic Web Forms model, ASP.NET MVC helps developers create Web applications in accordance with a widely
recognized design pattern: the Model View Controller.
Today, the overall ASP.NET platform is made up of a few distinct components: Web Forms, ASP.NET MVC,
Dynamic Data controls and ASP.NET AJAX. The upcoming ASP.NET 4.0 platform has the same foundation as the
latest 3.5 SP1 version, but it provides further refinement in the areas of Web Forms, Dynamic Data controls and, last
but not least, ASP.NET AJAX.
In this article, I'll take a look at what's new and improved in the Web Forms model. In future columns, I'll address
the Dynamic Data control platform as a whole and explore in-depth the developments in the ASP.NET AJAX
environment.
ASP.NET Web Forms 4.0 at a Glance
The key words to describe what's new in the overall ASP.NET 4.0 platform are "more control." ASP.NET 4.0 is
neither a revolutionary change nor a refactoring of its existing architecture. It consists, instead, of a good number of
small-scale changes that together provide developers with much more control of certain frequently used features of
the existing framework.
For example, ASP.NET 4.0 Web Forms give developers more control over viewstate management, generation of
IDs in the context of data-bound controls, and HTML generated by some template-based controls. In addition, you'll
find new families of pluggable components for features that weren't supporting the provider 2009 model in earlier
versions of ASP.NET and a finer control over the linking of external script files through the ScriptManager control.
Let's start with viewstate management.
More Control Over the Viewstate
I say nothing new by stating that the viewstate has been one of the most controversial features of ASP.NET since the
advent of the platform. Too many developers are still convinced that the viewstate is a waste of bandwidth and an
unacceptable burden for each and every ASP.NET page. Nearly the same set of developers eagerly welcomed
ASP.NET MVC because of its complete absence of viewstate. Recently, while teaching an ASP.NET MVC class, I
discussed a master/detail scenario in which the user could select a customer from a list to see more details. I
populated the list during the loading of the page, as expected. Next, while handling the selection-changed event, I
showed how to fill in the customer's details. However, to have the list available for another selection, I also had to
explicitly repopulate it.
Students promptly noted the extra work required to fill in the list at every server action. Couldn't this be
automatically filled as in Web Forms? Well, in ASP.NET Web Forms you don't need to refill data-bound controls
over a postback just because of the viewstate.
In short, the viewstate is not there only to reduce your bandwidth. The viewstate is functional to the Web Forms
model, as it caches some of the content for the controls in the page. Next, the ASP.NET infrastructure takes care of
reading that information from the viewstate to restore the last known good state for each control within the page.
As widely known, but also largely overlooked, the viewstate is an optional feature. The viewstate support is turned
on for each page by default, but developers have a Boolean property available to change the default setting and do
without it. The property is named EnableViewState and is defined on the System.Web.UI.Control class. It should be
noted that the System.Web.UI.Page class inherits from the Control class. As far as the viewstate is concerned, an
individual control and the page are one and the same.
For any ASP.NET page, turning off the viewstate couldn't be easier. You set EnableViewState to false either
declaratively or programmatically during the page's life cycle, as follows:
void Page_Load(object sender, EventArgs e)
{
Figure 1 The ViewStateMode Enumeration
Value Description
Inherit Inherits the value of
ViewStateMode property
from the parent control.
Enabled Enables viewstate for this
control even if the parent
control has viewstate
disabled.
Disabled Disables view state for this
control even if the parent
control has viewstate
enabled.

msdn magazine
2
Cutting Edge
// Disable viewstate for the page
// and ALL of its child controls
this.EnableViewState = false;
...
}
The EnableViewState property indicates whether the control is allowed to cache its own UI-related state. Be
reminded that the viewstate setting in ASP.NET has a hierarchical nature, which means that if the viewstate is
enabled on the parent control, it cannot be disabled on any of its child controls. The following code has no effect on
the behavior of the text box if the viewstate is enabled at the page or container level:
protected void Page_Load(object sender, EventArgs e)
{
TextBox1.EnableViewState = false;
}
The IsViewStateEnabled property -- a protected property indeed -- reports about the current state of the viewstate for
a control. But what does all of this mean to developers?
If the viewstate is enabled on the page (which is the default setting), you have no means to keep the state of
individual controls off the storage. To gain some control over it in ASP.NET 3.5, you need to disable the viewstate
at the page level and then re-enable it where needed, but also keep in mind the hierarchical nature of it. Any
container control that has the viewstate enabled will inevitably push its setting down to the list of its children. This
fact leads to somewhat of a paradox: it is possible for the same control to have the property IsViewStateEnabled set
to true and the property
EnableViewState set to false!
The viewstate is a fundamental piece of the ASP.NET Web Forms architecture, and dropping it entirely from the
platform in the name of a performance gain is arguably not the best option. Years of experience has proved that a
more sustainable option is having the viewstate disabled by default on the page. Even better than that is the change
coming up with ASP.NET 4.0: enabling viewstate control over individual controls.
In ASP.NET 4.0, the System.Web.UI.Control class exposes a new property named ViewStateMode:
public virtual ViewStateMode ViewStateMode { get; set; }
The property takes its feasible values from the ViewStateMode enumerated type, shown in Figure 1.
To preserve compatibility, the default value of the property is Inherit. However, this property gives developers the
possibility of controlling the viewstate setting for individual controls, regardless of the viewstate option of any
parent page or containers.
Only a few of the controls in ASP.NET pages really need viewstate. For example, all text boxes you use to simply
gather text don't need viewstate at all. If Text is the only property you use on the control, then the value of the Text
property would be preserved by cross-page postbacks because of posted values. Any value stored in the viewstate, in
fact, will be regularly overwritten by the posted value. In this case, the viewstate is really unnecessary. But there's
more to notice. Any side properties that are set to a given non-default value on creation, but remain unchanged
during postbacks (such as ReadOnly, BackColor and so on), have no need to go to the viewstate. For example, a
Button control that retains the same caption all the time doesn't need the viewstate at all. Up until ASP.NET 4.0,
turning off the viewstate for individual controls was problematic. Things change in the next version. This is the key
takeaway of the ViewStateMode property.
More Control Over Auto-Generated IDs
In ASP.NET pages, using the same ID for two server controls isn't allowed. If this happens, the page won't compile -
- period. In HTML, though, it is possible for two or more elements to share the same ID. In this case, when you
make a search for an element via document.getElementById, you'll simply get an array of DOM elements. What
about nested ASP.NET controls?
Most data-bound, template-based controls generate their output by repeating an HTML template for every data-
bound item. This means that any child control defined with a unique ID in the template is being repeated multiple
times. The original ID can't just be unique. For this reason, since the beginning, the ASP.NET team defined an
algorithm to ensure that every HTML element emitted by an ASP.NET control could be given a unique ID. The ID
resulted from the concatenation of the control ID with the ID of the naming container. Furthermore, in case of
repeated controls (i.e., templates), a numeric index was added for disambiguation. For years, nobody really cared
about the readability of the auto-generated ID, and strings like the following became fairly common:
ctl00$ContentPlaceHolder1$GridView11$TextBox1
Looking at this, the first issue that may come to mind is the potential length of the string, which, repeated for several
elements, makes the download larger. More important, such an approach is problematic from a client script
perspective. Predicting the ID of a given control you want to script from the client is difficult, and leads straight to
hard-to-read code. In the first place, you need to know the detailed name being generated for a given HTML element
that is buried in the folds of a grid or any other naming container controls. Second, this name is subject to change as
you rename one of the server controls along the hierarchy. A frequently used trick is the following:
var btn = document.getElementById("<% =Button1.ClientID %>");
The trick consists in using ASP.NET code blocks to insert in the HTML source code being generated for the real
client ID of a given control. When master pages or template-based controls are used, the trick is a real lifesaver,
because in this case, the naming container of a plain control ends up being quite a complex hierarchy of controls that
developers often leave unnamed. The actual name of the control, therefore, is subject to a few auto-generated IDs.
In addition to using code blocks, ASP.NET 4.0 supports another option: more control over the algorithm that
generates the client ID of a server control.
The System.Web.UI.Control class now features a brand new property named ClientIDMode. The property can
assume a few predefined values as detailed in Figure 2.
Admittedly, the ID-generation algorithm, especially when master pages are involved, is not easy to understand. It is
guaranteed to generate unique IDs, but ends up with strings that are really hard to predict. A more predictable option
has been introduced primarily to be used with data-bound controls so that developers can easily guess the ID of, say,
a Label control used to render a given property on the nth data item. In this case, you want the ID to reflect the
hierarchy of the control (simplifying the naming container structure to the parent controls) but also a particular key
value, such as the primary key. Consider the following code:
<asp:GridView ID="GridView1" runat="server"
ClientIDMode="Predictable"
RowClientIdSuffix="CustomerID">
...
</asp:GridView>
In this case, each row of the grid is identified by one or more columns in the data source with a trailing index. Here's
an example:
Panel1_GridView1_ALFKI_1
The GridView is the sole control to support multiple columns. If you have multiple columns to concatenate, then
you use the comma to separate names. The ListView will accept only one column, whereas the Repeater control will
limit to trail a 0-based index and accept no column name.
Finally, note that the ClientIDMode property affects only the ID attribute of the resulting HTML element. By
design, the name attribute remains unchanged.
View Controls Refinements
Most data-bound controls offer the ability to select a given displayed element -- mostly a row. In previous versions
of ASP.NET, the selection was stored as the index of the selected item within the page. This means that for pageable
controls (such as the GridView control), the same selection made on, say, page one is retained on page two unless
you programmatically reset the selection during the page/changing event.
In ASP.NET 4.0, the current selection on a data-bound control is tracked via the value on the data key field you
indicate through the DataKeyNames property. To enable this feature, you use the new PersistSelection Boolean
property and set it to true. The default value is false for compatibility reasons.
In addition, the FormView and ListView controls offer a little better control over their generated HTML markup. In
particular, the FormView now accounts for a brand new RenderTable Boolean property. If you set it to false (the
default is true), then no extra HTML table tags will be emitted and the overall markup will be easier to style via
CSS. The ListView no longer needs a layout template in ASP.NET 4.0:
<asp:ListView ID="ListView1" runat="server">
<ItemTemplate>
<% Eval("CompanyName")%>
<hr />
</ItemTemplate>
</asp:ListView>
The preceding code snippet is sufficient to repeat the content of the CompanyName column for each element in the
data source.
HTML Enhancements
In the beginning, ASP.NET didn't offer much programmatic control over all possible tags of a Web page. For a long
time, the title of a page missed an ad hoc property on the Page class. The same could be said for other popular
features, like CSS files.
In ASP.NET 4.0, the Page class exposes two new string properties to let you set some common tags in the <head>
section of a page. The two new properties are Keywords and Description. The content of these server properties will
replace any content you may have indicated for the metatags as HTML literals.
The Keywords and Description properties can also be set directly as attributes of the @Page directive, as in the
following example:
<%@ Page Language="C#"
AutoEventWireup="true"
CodeFile="Default.aspx.cs"
Inherits="_Default"
Keywords="ASP.NET, AJAX, 4.0"
Description="ASP.NET 4.0 Web Forms" %>
In ASP.NET, when you invoke Response.Redirect, you return the browser an HTTP 302 code, which means that the
requested content is now available from another (specified) location. Based on that, the browser makes a second
request to the specified address, and that's it. A search engine that visits your page, however, takes the HTTP 302
code literally. This is the actual meaning of the HTTP 302 status code in that the requested page has been
temporarily moved to a new address. As a result, search engines don't update their internal tables and when the user
clicks to see your page, the engine returns the original address. Next, the browser gets an HTTP 302 code and makes
a second request to finally display the desired page.

To smooth the whole process, in ASP.NET 4.0 you can leverage a brand new redirect method, called
RedirectPermanent. You use the method in the same way you use the classic Response.Redirect, except that this
time, the caller receives an HTTP 301 status code. Code 301 actually means that the requested content has been
permanently moved. For the browser, it makes no big difference, but it is a key difference for search engines.
Search engines know how to process an HTTP 301 code and use that information to update the page URL reference.
Next time they display search results that involve the page, the linked URL is the new one. In this way, users can get
to the page quickly and save themselves a second round-trip.
More Control over Output Caching
In ASP.NET 2.0, several key parts of the ASP.NET runtime were refactored and made much more flexible and
configurable. This was achieved through the introduction of the provider model. The functionality of some
ASP.NET core services, including session state, membership and role management, were abstracted to a sort of
service contract so that different implementations of a given service could be used interchangeably and
administrators could indicate the one they wanted from the configuration file.
For example, under the hood of the old faithful Session object, there's an instance of the HttpSessionState class
whose content is retrieved by the selected session state provider. The default session state provider gets data from
the in-process memory (specifically, from a slot within the Cache dictionary), but additional providers exist to store
data in databases and external host processes.

In ASP.NET 4.0, the provider model covers another extremely important feature of ASP.NET that for some reason
was left behind in previous versions: the output caching.
There are many situations where it is acceptable for a page response to be a little stale if this brings significant
performance advantages. Think of an e-commerce application and its set of pages for a products catalog, for
example. These pages are relatively expensive to create because they could require one or more database calls and
likely some form of data join. Product pages tend to remain the same for weeks and are rarely updated more than
once per day. Why should you regenerate the same page a hundred times per second? Since ASP.NET 1.0, output
caching allows you to cache page responses so that following requests can be satisfied returning the cached output
instead of executing the page. Figure 3shows the sequence of application events, including the step where the
system attempts to resolve the request looking into the output cache.
Figure 5 Split Script Files in the Microsoft AJAX Library for ASP.NET 4.0
File Goal
MicrosoftAjaxCore.js Core functionalities of the library
MicrosoftComponentModel.js Base classes for the client-side object
model
MicrosoftAjaxSerialization.js JSON serialization
MicrosoftAjaxGlobalization.js Data and funtions for globalization
MicrosoftAjaxHistory.js History points and the client API for
history management
MicrosoftAjaxNetwork.js Raw AJAX and HTTP functionalities
MicrosoftAjaxWebServices.js Wrapper client API for invoking
services
MicrosoftAjaxApplicationServices.js Wrapper client API for predefined
ASP.NET services such as
authentication
MicrosoftAjaxTemplates.js Client-side rendering API for ASP.NET
AJAX 4.0
MicrosoftAjaxAdoNet.js Wrapper client API for ADO.NET
services in ASP.NET AJAX 4.0


Up until now, any page output (which can be grouped by form and query string parameters, requesting URL, or
custom strings) is stored in memory in a private area of the ASP.NET Cache. In the long run, the amount of the
output cache puts additional pressure on the Web server machine by consuming memory and generating frequent
updates on the Cache object. In ASP.NET 4.0, the output caching subsystem fully supports the provider model, thus
giving developers the opportunity of storing page responses outside the ASP.NET worker process.A custom output
cache provider is a class that derives from OutputCacheProvider. The name of the class must be registered in the
configuration file, as shown below:
<caching>
<outputCache defaultProvider="AspNetInternalProvider">
<providers>
<add name="DiskCacheProvider"
type="Samples.DiskCacheProvider, MyProvider"/>
</providers>
</outputCache>
</caching>
As usual, you can have multiple providers registered and select the default one via the defaultProvider attribute on
the outputCache node. The default behavior is offered through the AspNetInternalProvider object that turns out to be
the default provider, if you don't change anything in the configuration file.
Figure 7 The MicrosoftAjaxMode Enumeration
Value Description
Enabled Legacy option, indicates that just
one file will be linked from the
pages as in previous versions of
ASP.NET.
Disabled No script file is automatically
referenced from the
ScriptManager control.
Explicit Script files to be referenced are
explicitly listed in the Scripts
section of the ScriptManager
control.
The output cache provider doesn't have to be the same for all pages. You can choose a different provider on a per-
request basis or even for a particular user control, page, or combination of parameters for a page. You can specify
the provider name in the @OutputCache directive wherever this directive (page and/or user controls) is accepted:
<% @OutputCache Duration="3600"
VaryByParam="None"
providerName="DiskCache" %>
To change the provider on a per-request basis, instead, you need to override a new method in global.asax, as shown
below:
{
// Decide which provider to use looking at the request
string providerName = ...;
return providerName;
}
Starting with version 2.0, session state can be stored outside the memory of the worker process. This means that any
data stored in the Session object must be serialized to and from an out-of-process environment. If you look back
at Figure 3, session state is loaded into the Session object around the AcquireRequestState application event. The
in-memory content is then serialized back to storage at the end of the request processing.
ASP.NET 4.0 enables developers to request some compression to be applied to the data stream being sent in and out
of the session provider (see Figure 4). Compression is obtained by using the GZipStream class instead of a plain
Stream class to do any serialization:
<sessionState mode="SqlServer" compressionEnabled="true" ... />
To enable compression, you simply add the compressionEnabled attribute to the sessionState section of the
configuration file. By default, compression is not enabled.
Any JavaScript library is made up of myriad specific JavaScript files with a more or less sophisticated graph of
interconnections. ASP.NET AJAX, instead, always tried to abstract JavaScript details away from developers and
offered a rather monolithic client JavaScript library, via the ScriptManager control. This will change in ASP.NET
4.0. The Microsoft AJAX client library has been refactored and split into the individual files listed in Figure
5. Figure 6 shows the dependencies between individual script files in the overall library.
A new property has been added to the ScriptManager control that lets you specify how the building blocks of the
library should be handled. The property is MicrosoftAjaxMode, and it accepts values as shown in Figure 7.
Better Platform
ASP.NET 4.0 Web Forms contains a number of small-scale changes that, taken together, make it a better
development platform. Web Forms is a mature framework that needs refinement, not redesign. If you don't feel
entirely comfortable with Web Forms and are looking for something completely different, then ASP.NET MVC is
worth a careful look.

Data Binding in ASP.NET AJAX 4.0

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 faade 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 markuptypically 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 attributedataview, in the preceding code snippetis 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!

Live Data Binding in ASP.NET AJAX 4.0
Dino Esposito
Recently I moved into a new office and went through the extremely pleasant and gratifying experience of packing
up all the programming books I had collected in more than 10 years.
Those books could tell you quite clearly how Web programming evolved in the past decade, and which technologies
followed one another, each improving (and in many cases revolutionizing) the other.
One book in particular caught my attention. It covered cutting-edge (well, for that era) programming techniques for
Internet Explorer 4. I couldnt resist the temptation to flip through its pages.
In the late 1990s, most big names in the computer industry were engaged in their first attempts to make the Web and
the browser a dynamic and highly programmable environment.
Data binding was just one of many popular features being researched and developed. While the basic idea of data
binding hasnt changed significantly over the years, a real transformation did occur as far as its application to the
Web world. The common approach to implementing data binding over the Web is radically different today than in
the late 1990s, and much of the difference is due to Asynchronous JavaScript and XML (AJAX).
In this column Ill discuss various forms of client-side data binding as they are coming out in ASP.NET AJAX 4.0.
In particular, Ill focus on some advanced features of data binding and observable objects.
Basic Principles
Generally speaking, data binding is simply a programs ability to bind some members of a target component to the
members of a data source. Rapid Application Development (RAD) tools such as Microsoft Access and Microsoft
Visual Basic made data binding a successful reality.
RAD tools offered an easy and effective infrastructure for developers to bind visual elements to the members of a
data source. For a long time, the data source was uniquely identified with a record-set data stream originating from a
SQL query.
In this regard, data binding nicely fits in a smart-client scenario but poses additional issues if employed in a Web-
client scenario. For example, how would you flow records from the origin database server down to the requesting
JavaScript-equipped browser?
Among many other things, that old book I opened up after years of oblivion discussed the data binding features of
IE4 based on a couple of special ActiveX components, aptly named the Tabular Data Control (TDC) and Remote
Data Services (RDS) control. Figure 1 illustrates the overall architecture of client-side data binding as it was
envisioned by IE4 architects in the beginning of the dynamic Web era.

Figure 1 Client-Side Data Binding in Internet Explorer 4
A made-to-measure ActiveX control manages the connection with a remote data source and takes care of
downloading (and optionally caching) data. The data source is any ODBC-compliant data source with RDS; its a
server-side text file with TDC.
The actual binding between source and target elements is implemented through browser-specific HTML attributes
such as datasrc, datafld and dataformatas. Heres a quick example:
<span id="Label1" datasrc="#rdsCustomers" datafld="CompanyName" />
The content of the bound fieldCompanyName in the exampletakes up the space reserved for the SPAN tag in
the resulting Document Object Model (DOM).
What does the actual job of inserting data into the DOM? As mentioned, its the browser that in this case does the
trick. When the browser encounters any dataXXX attributes, it queries the data source control for data using an
internal, contracted API. Any data it gets is then inserted into the final DOM and displayed to the user.
As you can see, the solution is strongly browser-specific and understandably never captured the heart of developers.
Client-side data binding was then set aside for a few years as ASP.NET and its server-side programming model
gained wide acceptance.
In recent years, the advent of AJAX generated a lot of interest around client-side data binding, and engineers were
back at work finding an effective (and this time cross-browser) way to make it happen.
Evolution in ASP.NET AJAX
Figure 2 shows the overall architecture of client-side data binding as its implemented in ASP.NET AJAX 4.0.

Figure 2 Client-Side Data Binding in ASP.NET AJAX 4.0
Although the architectures depicted in Figure 1 and Figure 2 may look similar at first glance, they actually differ in
a number of key aspects.
First and foremost, with ASP.NET AJAX 4.0 you can build client-side data-binding solutions that work with any
modern browser. The glue code required to actually bind source data to target elements is now part of the Microsoft
Ajax JavaScript library. As such, it can be hosted in any browser.
Furthermore, for binding you no longer have proprietary and non-standard HTML attributes such as datasrc and
datafld that the browser must resolve. Instead, binding information is specified using XHTML-compliant,
namespaced custom attributes resolved by code in the JavaScript library. It can also be done imperatively.
Old-Style versus New-Style
Another significant difference lies in the structure of the data source object. In old-style data binding, you use a sort
of black-box proxy that manages data retrieval for you. In ASP.NET AJAX 4.0, you dont need any such ActiveX or
binary components. All you need is a JavaScript object with the source data.
The built-in binding infrastructure links together fields on the JavaScript source object and elements of the DOM.
In ASP.NET AJAX 4.0, such a binding infrastructure is built into the Sys.UI.DataView component. Functionally
speaking, the DataView object operates in much the same way as the RDS control does in IE4-style client data
binding. It connects directly to a remote endpoint to get and expose data.
However, there are some differences. The DataView object is a client control entirely written in JavaScript that
requires no special support from the browser to run. As you can see, its quite different from the RDS ActiveX
control.
Moreover, the DataView control doesnt directly interface with a relational data source. Instead, it connects to any
JavaScript Object Notation (JSON)- or JSON With Padding (JSONP)-enabled service, such as a Windows
Communication Foundation endpoint, and exchanges data using JSON. The service can wrap any physical data store
(including a relational database) or even be a plain wrapper around an Entity Framework model. As Figure 2
illustrates, in ASP.NET AJAX 4.0 you can even have data binding in place without an outbound network connection
to the server. If, say, upon loading, a page downloads some data onto the client machine, you can have data binding
at work on locally cached data without any further roundtrip to the server.
A Brief Summary
In the October 2009 installment of the Cutting Edge column (msdn.microsoft.com/magazine/ee309508.aspx), I
covered the basics of data binding in ASP.NET AJAX 4.0 from a developers perspective. While you can still refer
to that article for deep coverage, Im going to provide here a brief summary of the most important programming
facts for client data binding.
In ASP.NET AJAX 4.0, client-side data binding can occur within a proper HTML template. A template is a DOM
tree decorated with the sys-template CSS attribute:
<div sys:attach="dataview1" class="sys-template">
...
</div>
The sys-template is a conventional name for a user-defined CSS style that at the very minimum includes the
following:
<style type="text/css">
.sys-template { display:none; }
</style>
Decorating a given HTML tag with the sys-template attribute is not enough, however. You must also add some
behavior to the tag that enables it to process any binding expressions inside. In this context, a behavior is just an
instance of a made-to-measure JavaScript component or control.
A behavior can be attached to an HTML tag, either by instantiating the behavior programmatically or by using a
declarative approach (by adding markup to the template tags in the page). For the declarative approach, the behavior
must be associated with a public name (namespace prefix).
Heres an example of assigning a public name to an instance of the DataView component:
<body xmlns:sys="javascript:Sys"
xmlns:dataview1="javascript:Sys.UI.DataView">
...
</body>
The sys:attach attribute gets a public name and creates an instance of the referenced behavior object. In the first code
example in this section, the DIV tag is empowered with the behavior expressed by the object named dataview1. As
you can guess, dataview1 is just the public name of the Sys.UI.DataView JavaScript object.
Once a DataView instance has been attached to an ASP.NET AJAX 4.0 template, the DataView can successfully
process any binding expressions contained in the templates. Heres a sample template with the simplest binding
syntax:
<ul id="imageListView" class="sys-template"
sys:attach="dataview1" dataview1:data="{{ imageArray }}">
<li>
<span>{{ Name }}</span>
<span>{{ Description }}</span>
</li>
</ul>
The {{expression}} token tells the DataView to process the embedded JavaScript expression and assign the result to
the DOM or the specified DataView property. For example, the code above assigns the content of a JavaScript
variable named imageArray to a DataView property named data. In this way, you define the data source of the
binding operation. This information is used to expand any other binding expressions within the template, such as
those used above in the body of the two SPAN tags. Name and Description are expected to be public properties on
the data item or items assigned to the data property of the DataView.
Inline Expression Evaluation
The {{expression}} syntax indicates the simplest type of binding supported by ASP.NET AJAX 4.0. Any bindings
expressed in this way are evaluated only when the template is rendered. They are never updated unless the template
is refreshed programmatically.
An inline expression is evaluated against the current state of the data source at rendering time, but doesnt
automatically capture any further changes made to the data source.
An alternative, richer binding model is also supported that gives you the same programming power of XAML data
binding in Windows Presentation Foundation and Silverlight applications. Such a set of advanced data binding
features are commonly referred to as live binding. Lets find out more.
Live Binding
Live binding ensures that the value displayed in the user interface is automatically updated any time the bound value
in the data source changes. For example, suppose you establish a live binding between a SPAN tag and the
CompanyName property in a data source. The SPAN tag displays the current value of the CompanyName property
at the time of rendering. However, the content of the SPAN tag will be automatically updated any time the bound
data source property undergoes changes. Live binding can be applied to any two objects, whether DOM elements or
JavaScript objects.
A different syntax is required for live binding expressions. Heres an example:
<span>{binding CompanyName}</span>
You use a single pair of curly brackets to wrap the expression, and prefix it with the keyword binding. As you can
see, the overall syntax has much in common with the equivalent XAML syntax, and that isnt coincidental.
It should be noted that the content of the SPAN tag shown earlier is updated whenever a change is detected on the
currently bound data item; the reverse wont work. If the content of the SPAN is updated, that change wont be
propagated to the source object.
Live binding also can be described as a one-way binding that may happen repeatedly as updates on the data source
are detected.
Hold on! The strategy employed to detect changes on bindings is a key point and Ill have more to say about it in a
moment, but not before introducing two-way binding.
Two-Way Data Binding
Two-way data binding is a special form of live binding that uses two channels to detect changes on the binding.
When two-way binding is in place between two objects, the following happens:
If the data source changes, the target object is automatically refreshed.
If the target object changes, the new state is propagated to the underlying data source.
Put another way, two-way data binding ensures that the source and target objects are always in sync.
No Tier Crossing
The following may perhaps sound like a foregone conclusion, but let me make it clear anyway. Imagine you have
two-way binding between a piece of user interface and some data that a service retrieved from a database.
The data downloaded from the server and bound to the visual elements of the user interface represent a snapshot of
the domain model. Say, for example, it represents a Customer object. If the displayed Customer object is modified in
a two-way binding page, then all detected changes are mirrored to the client-side Customer object, but in no way
will they be propagated to the server. Two-way data binding doesnt cross any tiers.
In terms of syntax, two-way binding is nearly the same as one-way live binding.
An ASP.NET AJAX binding is expressed via a Sys.Binding JavaScript object. You can control the direction of the
data flow through the mode attribute on the Sys.Binding object that the framework creates for you any time you use
the live binding syntax. (Note that no Sys.Binding object is created when you opt for plain {{...}} inline
expressions.)
The following code snippet shows how to set up two-way data binding using the mode attribute:
<span id="Label1">{binding CompanyName, mode=twoWay}></span>
Possible values for the mode attribute are summarized in Figure 3.
Member Value Description
auto 0 Data flow is twoWay if the target is an input element, select element,
textArea element or component that implements the
Sys.INotifyPropertyChange Interface. Data flow is oneWay otherwise.
oneTime 1 Data is transferred from the source object to the target only one time when
the template is rendered.
oneWay 2 Data is transferred from the source object to the target whenever the source
is updated.
twoWay 3 Data is transferred from the source object to the target whenever the source
is updated, and from target to source whenever the target is updated.
oneWaytoSource 4 Data is transferred from target to source whenever the target is updated.
Figure 3 The Sys.BindingMode Enumeration
Live Binding in Action
Figure 4 shows sample code that demonstrates live, two-way data binding. The page contains one template that is
rendered using a DataView control. The data source object is a JavaScript array named theCustomers. Dont be
fooled by the fact that theCustomers is a local object statically defined within the client browser. What really matters
is that theCustomers is ultimately assigned to the data property of the DataView object. The DataView object has a
rich programming interface that allows you to put into the data property any content, including content downloaded
from a Web service.
<asp:Content ID="Content2" runat="server" ContentPlaceHolderID="PH_Head">

<link rel="stylesheet" type="text/css"
href="../../Css/lessantique.css" />
<style type="text/css">
.sys-template { display:none; }
</style>

<script type="text/javascript">
var theCustomers = [
{ ID: "ALFKI", CompanyName:
"Alfred Futterkiste" },
{ ID: "CONTS", CompanyName:
"Contoso" }
];
</script>
</asp:Content>

<asp:Content ID="Content5"
ContentPlaceHolderID="PH_Body"
runat="server">

<asp:ScriptManagerProxy
runat="server">
<Scripts>
<asp:ScriptReference Path=
"http://ajax.microsoft.com/ajax/beta/0910/MicrosoftAjaxTemplates.js" />
</Scripts>
</asp:ScriptManagerProxy>

<div id="customerList">
<ul class="sys-template"
sys:attach="dataview" dataview:data="{{ theCustomers }}">
<li>
<span><b>{binding ID}</b></span>
<input type="text" id="TextBox1"
value="{binding CompanyName}" />
<br />
<span>Currently displaying...
<b>{binding CompanyName}</b></span>
</li>
</ul>
</div>
</asp:Content>
Figure 4 Live, Two-Way Binding Sample
For each bound data item, the template emits an LI tag that includes a text box. The text box is bound to the
CompanyName property of the source. In the same template, a SPAN tag is also bound to the CompanyName
property of the source.
Note that live bindings are not limited to the template they belong to. You can have the same expressionsay,
{binding CompanyName}in two different templates. As long as the same data source object (or a compatible
object) is attached to both templates, the binding will always be correctly resolved. Figure 5shows the page in
action.

Figure 5 Live Binding in Action
Initially the text box and the SPAN tag contain the same data. However, at some point the user may start editing the
name of the company in the text box. Nothing happens until the user tabs out of the text box.
The editing phase is considered complete as soon as the text box loses focus. At this point, the two-way data binding
mechanism triggers and updates the underlying data source object. Because the SPAN tag is also bound to the same
data property through live binding, any changes are propagated.
To prevent the automatic update of the data source when an INPUT element is involved, you set the mode property
explicitly, as shown below:
<input type="text" value="{binding CompanyName, mode=oneWay}" />
Enter this change to the code in Figure 4 and see the difference.
Detecting Changes
When the mode property of a binding is not set explicitly, it takes the auto value as described in Figure 3. So when
you attach a binding to any HTML elements that refer to input scenarios (such as INPUT, SELECT or
TEXTAREA), the property mode defaults to twoWay. As a result, all the changes to the target made via the
browsers user interface are automatically transferred to the source.
Note that there are two variations of a oneWay binding. The standard oneWay binding detects changes in the source
and reflects them in the user interface. The alternate oneWayToSource does the reverse: it detects changes in the
target and reflects them in the source object. Try using the following code:
<input type="text" value="{binding CompanyName, mode=oneWayToSource}" />
The initial display of the page will contain empty text boxes. As you type, though, the new text is detected and
processed as expected.
The two-way data binding option is also the default option for any bound JavaScript object that happens to
implement the Sys.INotifyPropertyChange interface. (The interface is part of the Microsoft Ajax JavaScript library.)
When I first introduced live binding, I said that the target is updated whenever the source changes. The following
explains which changes the framework can detect and how.
HTML input elements fire standard events when their state is changed or, at a minimum, they notify when they enter
or exit an editing phase. Because these events are part of the HTML standard, any data binding solution based on
that standard will work on any browsers.
For an update to one side of the binding to be reflected in the other, it has to be done in a way that is possible to
detect. Suppose you have a binding where the source is a JavaScript array, as shown here:
<ul class="sys-template" sys:attach="dataview"
dataview:data="{{ theCustomers }}">
<li>
<span ><b>{binding CompanyName}</b></span>
</li>
</ul>
Try to update the CompanyName property on an object within the array. The markup shows a button that if clicked
runs the enterChanges JavaScript function, shown here:
<span>{binding CompanyName}</span>
<input type="button" value="Enter changes"
onclick="enterChanges()" />
...
<script type="text/javascript">
function enterChanges() {
theCustomers[0].CompanyName =
"This is a new name";
}
</script>
The enterChanges function updates the CompanyName property on the first object in the array. As you can see, this
clearly is an operation that updates the state of a bound object.
In the case of live binding, you should expect the SPAN tag to display the new value. If you try that, though, you
will see that nothing happens.
That is because there is no cross-browser way to be notified of updates occurring to a plain old JavaScript object
such as that. So changes happen but the binding isnt aware of them and the user interface isnt refreshed.
Would polling the state of a plain JavaScript object be a viable solution? Probably not, and the development team
reasonably ruled out that option, essentially for scalability reasons.
In the end, is using input HTML elements bound to data the only possibility for making data changes in a way that
will successfully trigger other live bindings? Well, not exactly. The Microsoft Ajax JavaScript library features a
static API through which you can "observe" the changes of any JavaScript object. This API is also available in a
flavor that transforms a plain JavaScript object into an observable object for the binding machinery to detect
updates.
Observable JavaScript Objects
An observable JavaScript object is an object endowed with additional functionality that raises change notifications
when modified. Additional functionality is codified through the Sys.Observer interface. Note that changes made
directly, without going through the interface, will not raise change notifications and will be ignored by the binding
infrastructure.
Observable objects fit perfectly in a scenario where you want to establish live bindings between visual elements and
JavaScript objects, such as those you might get from a remote Web service.
There are two ways to work with observable objects. One entails that you make a given object observable by adding
some dynamic code to itnot enough to make a plain JavaScript object a complex thing, but enough to add new
capabilities. Here is an example:
<script type="text/javascript">
var theCustomers = [
{ ID: "ALFKI", CompanyName:
"Alfred Futterkiste" },
{ ID: "CONTS", CompanyName:
"Contoso" }
];
function pageLoad() {
Sys.Observer.makeObservable(theCustomers);
}

function onInsert() {
var newCustomer = { ID: "ANYNA",
CompanyName: "AnyNameThatWorks Inc" };
theCustomers.add(newCustomer);
}
</script>
The Sys.Observer.makeObservable method takes a JavaScript object (including arrays) and adds methods to it that
you can use to make changes to the object that the bindings can detect. Note that having an observable array
provides methods for changing the array in an observable wayso you can detect insertions and deletions. But it
does not automatically provide the corresponding methods for modifying the properties of the individual items in the
array in an observable way. For that, you can separately call makeObservable on the individual items, and they will
then also have additional methods added.
As I mentioned earlier, the following code associated with a click event wont trigger the binding:
<script type="text/javascript">
function enterChanges() {
theCustomers[0].CompanyName =
"This is a new name";
}
</script>
This code, however, will trigger the binding:
<script type="text/javascript">
function enterChanges() {
System.Observer.setValue(theCustomers[0],
"CompanyName", "New name");
}
</script>
What if the observed object has child objects? No worries: the setValue method knows how to handle the "dotted"
syntax:
System.Observer.setValue(theCustomers[0], "Company.Address.City", "Rome");
Finally, note that the observer pattern can be applied to any object you may encounter in the context of a Web page,
including DOM elements, behaviors and even browser objects such as window.
Static and Dynamic
Most times when you need data binding in an application, you also need it to be live, at least one-way, if not two-
way. In ASP.NET AJAX 4.0, data binding can be both staticthat is, a simple inline evaluation of data values
during renderingand dynamic, in the sense that it can detect changes in source or target and apply them.Not all
updates can be detected and used to refresh bindings. ASP.NET AJAX 4.0 easily recognizes changes entered into
bound objects through visual elements. But for changes entered programmatically into JavaScript objects or arrays,
theres no reliable cross-browser way to have live detection of changes. The trick in ASP.NET AJAX consists of
providing a way to make changes so that theyre observable and thus can be detected by live bindings. This takes the
form of appending some observable operations to the object or, as an alternative, using ad hoc Sys.Observer static
methods to conduct updates.

Conditional Rendering in ASP.NET
AJAX 4.0
Dino Esposito
Client-side rendering is by far the most exciting, and long-awaited, new feature youll find in ASP.NET AJAX 4.
Client-side rendering allows you to use HTML templates to define your desired layout and supplies a text-based
syntax for placeholders of run-time data. It all looks like server-side data binding, except that it takes place within
the client browser with external data downloaded via Web services.
Last month, I covered the basics of the new DataView client control and the binding techniques that will be most
commonly used. In this article, Ill go one step further and cover conditional template rendering.
Conditional Template Rendering
In ASP.NET AJAX 4, an HTML template for data binding is a piece of markup that may contain ASP.NET markup,
HTML literals and some placeholders for run-time data. The rendering algorithm is fairly simple: bound to such
templates, the DataView control fetches some data and uses that to fill up the template. The resulting markup, with
actual data substituted for placeholders, is then displayed in lieu of the original HTML template.
There are a couple of ways in which you can create an instance of the DataView control: declaratively or
programmatically. However, the algorithm used to generate the markup remains the same. This is where we left the
matter in last months article.
Going forward, a question springs up naturally. What if some logic is required to render the template? What if you
need conditional rendering that produces a different markup based on different run-time conditions? Some client-
side code must be intertwined with markup to check the values of data items being bound as well as the state of
other global JavaScript objects.
ASP.NET AJAX 4 defines a special set of namespaced attributes through which you attach custom behaviors to the
HTML template. These behaviors are JavaScript expressions to be evaluated and executed at very specific stages of
the rendering process. Figure 1 lists the predefined code attributes for conditional template rendering.
Code attributes are recognized by the template builder and their content is appropriately used in the rendering
process. Attributes in Figure 1 can be attached to any DOM elements used in an ASP.NET AJAX template.
Note that attributes in Figure 1 were scoped in the code: namespace up until Preview 4 of the ASP.NET AJAX 4
library and Visual Studio 2010 beta 1. Starting with Preview 5, the ASP.NET team eliminated the code: namespace,
and it is using only the sys: namespace for everything.
Figure 1 Attributes for Conditional Rendering of DOM Elements Within a Template

Conditional Rendering in Action
The sys:if attribute is assigned a Boolean expression. If the expression returns true, then the element is rendered;
otherwise, the algorithm proceeds with the next step. Heres a trivial example, just to quickly illustrate the point:
<div sys:if="false">
:
</div>
While processing this markup, the builder just ignores the DIV tag and all of its content. In a certain way, the sys:if
attribute can be used to comment out parts of the template at development time. All in all, assigning a constant value
of false to the sys:if attribute is not much different from doing the following in C#:
if (false)
{
:
}
Setting sys:if to a false value, doesnt exactly hide a HTML element. It should be noted that any ASP.NET AJAX
template is initially treated like plain HTML by the browser. This means that any template is fully processed to a
document object model (DOM) tree. However, as an ASP.NET AJAX template is decorated with the sys-template
attribute, nothing of the DOM tree shows up when the page is displayed. In fact, the sys-template attribute is a CSS
class that contains the following:
.sys-template { display:none; visibility:hidden; }
The sys:if attribute keeps the HTML element off the actual markup for the template. The sys:if attribute is ignored if
attached to a HTML element outside any ASP.NET AJAX templates. The sys:if attribute is not currently associated
with an else branch.
If defined, the sys:codebefore and sys:codeafter attributes execute before and after the rendering of the HTML
element. The two attributes can be used together or individually as it best suits you. The content of the attributes
must be a piece of executable JavaScript code.
Altogether, the code attributes give you enough power to deal with nearly every possible scenario, even though not
always with a straightforward solution. Lets consider a less trivial example of sys:if and sys:codebefore.
By the way, you may have noticed a few weird $-prefixed variables in the preceding code. Let me briefly introduce
them just before introducing the example.
Template Pseudo-Variables
In the custom code you use within the code attributes of a template, you have access to the full set of public
properties of the data item. In addition, you can access some extra variables defined and exposed by the template
builder for your convenience.
Currently, the documentation refers to them as pseudo-columns but I personally like the term pseudo-
variable. Figure 2 lists them all.
These pseudo-variables provide a glimpse of the internal state of the rendering engine as it is working. You can use
any of such variables as you would use any JavaScript variable in the ASP.NET AJAX template.
Figure 2 Pseudo-Variables Supported by the ASP.NET AJAX Template Builder

Coloring Matching Rows in a Table
As an example, lets consider a page that shows a list of customers plus a drop-down list to pick up a country/region.
Whenever a new country/region is selected, the list of customers refreshes to render customers from that
country/region in a different style (see Figure 3).

Figure 3 A Sample ASP.NET AJAX Page with Conditional Template Rendering
Figure 4 shows the markup for the sample page. As you can see, the page is a content page associated with a master
page. The required Sys namespace is declared in the Body tag defined in the master page.
Figure 4 Code Attributes in Action
<asp:Content ContentPlaceHolderID="PH_Body" runat="server">
<asp:ScriptManagerProxy runat="server" ID="ScriptManagerProxy1">
<Scripts>
<asp:ScriptReference Name="MicrosoftAjax.js"
Path="~/MicrosoftAjax.js" />
<asp:ScriptReference Path="~/MicrosoftAjaxTemplates.js" />
</Scripts>
</asp:ScriptManagerProxy>
<div>
<asp:DropDownList ID="listOfCountries" runat="server"
ClientIDMode="Static"
onchange="listOfCountries_onchange()">
</asp:DropDownList>
<table id="gridLayout">
<tr>
<th>ID</th>
<th>COMPANY</th>
<th>COUNTRY</th>
</tr>
<tbody id="grid" class="sys-template">
<tr sys:if="$dataItem.Country != currentCountry">
<td align="left">{{ ID }}</td>
<td align="right">{{ CompanyName }}</td>
<td align="right">{{ Country }}</td>
</tr>
<tr sys:if="$dataItem.Country == currentCountry"
class="highlight">
<td align="left"
sys:codebefore="if($dataItem.Country == 'USA') {
$element.style.color = 'orange';
$element.style.fontWeight=700;
}">
{{ ID }}
</td>
<td align="right">{{ CompanyName }}</td>
<td align="right">{{ Country }}</td>
</tr>
</tbody>
</table>
</div>
</asp:Content>
You should note that Preview 5 of ASP.NET AJAX requires you to override the MicrosoftAjax.js file that comes
with the ScriptManager control and beta 1. This is a temporary fix that will no longer be necessary as assemblies are
updated to beta 2 and then to release to manufacturing.
Before coming to grips with ASP.NET AJAX templates, let me focus on the markup code for the drop-down list
control.
Setting up the Drop-Down List
The code for the drop-down list for countries/regions is as follows:
<asp:DropDownList ID="listOfCountries" runat="server"
ClientIDMode="Static"
onchange="listOfCountries_onchange()">
</asp:DropDownList>
As you can see, the control assigns a value to the new ClientIDMode property and provides a client-side handler for
the DOM-level onchange event. The control is bound to its data on the server, precisely in the classic Page_Load
method:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Fetch data
string[] countries = new string [] {"[All]", "USA", ... "};
// Serialize data to a string string countriesAsString = "[All], USA,
...";
// Emit the array in the page this.ClientScript.RegisterArrayDeclaration(
"theCountries", countriesAsString);

// Bind data to the drop-down list
listOfCountries.DataSource = countries;
listOfCountries.DataBind();
}
}
The binding procedure is articulated in two steps. First, a JavaScript array is emitted in the response that contains the
same data bound programmatically to the DropDownList control. Next, the classic server-side data binding takes
place.
This technique is known as Dual-Side Templating and is a variation of the standard client-side data binding pattern.
The difference consists in the fact that data to bind is fetched on the server the first time the page is accessed and
served to the client as an embedded JavaScript array.
Further client-side data binding that proves necessary can then take place using the embedded array. In this way, you
basically save an extra roundtrip to get the data. This variation of the classic client data binding is helpful when you
display static data that dont change during the user interaction. In the example, I used this technique only for getting
the list of countries/regions; the list of customers, instead, is fetched from the Web server using a Web service.
When you use a server-side control to emit HTML markup, you may have little control over the actual ID if youre
using a master page. In ASP.NET AJAX 4, the new ClientIDMode property gives you more flexible ways to deal
with the issue.
In particular, if you set ClientIDMode to Static as in the example, then the client ID of the HTML element will
match exactly the server ID. This trick is not useful when youre going to repeat that server control in the context of
a data-bound templated control.
The following script code handles the change of selection event in the drop-down list:
<script language="javascript" type="text/javascript">
var currentCountry = "";
function listOfCountries_onchange() {
// Pick up the currently selected item
var dd = $get("listOfCountries");
currentCountry = dd.options[dd.selectedIndex].value;

// Refresh the template
refreshTemplate();
}

function refreshTemplate() {
var theDataView = $find("grid");
theDataView.refresh();
}
</script>
Note that this code will raise a JavaScript error if you dont set the ClientIDMode property of the DropDownList
control to Static. This is because of the ID-mangling work that ASP.NET usually does to ensure that when master
pages are used each produced HTML element has a unique ID.
The preceding onchange event handler saves the name of the currently selected country/region to a global JavaScript
variable and then refreshes the ASP.NET AJAX template. Lets focus on templates now.
Conditional Templates
The template is created and populated programmatically as below:
<script language="javascript" type="text/javascript">
function pageLoad()
{
dv = $create(Sys.UI.DataView,
{
autoFetch: true,
dataProvider: /ajax40/mydataservice.asmx",
fetchOperation: LookupAllCustomers"
},
{},
{},
$get(grid")
);
}
</script>
The DataView client control makes a call to the specified Web service, performs the given fetch operation and uses
any returned data to fill the ASP.NET AJAX template rooted in the DOM element named grid.
The overall template is rendered using a DataView instance bound to the return value of the LookupAllCustomers
method on the sample Web service. The method returns a collection of Customer objects with properties such as ID,
CompanyName and Country.
The template will stay bound to its data for the entire lifetime of the page regardless of the changes that may occur
to the data. What if, instead, you just want to modify the rendering of the templateno data refresh whatsoeveras
certain run-time conditions change? To get this, you need to insert code attributes in the template.
What you really need here is a truly conditional rendering that renders the template in one way if a given condition
is verified and otherwise if the condition is not verified. As mentioned, the sys: if attribute doesnt support if-then-
else semantics, and all it does is rendering, or ignoring, its parent element based on the value of the Boolean guard.
A possible workaround to simulate the two branches of a condition consists in using two mutually exclusive portions
of template, each controlled by a different Boolean expression. Also shown in Figure 4, the code follows the
schema below:
<tr sys:if="$dataItem.Country != currentCountry">
:
</tr>
<tr sys:if="$dataItem.Country == currentCountry"
class="highlight">
:
</tr>
The variable currentCountry is a global JavaScript variable that contains the name of the currently selected
country/region. The variable is updated every time the onchange event is raised by the HTML markup for the server-
side DropDownList control.
In the preceding code snippet, the former TR element is rendered conditionally based on the value of the Country
property of the data item being bound. If the variable matches the selected country/region, the former TR is skipped.
This behavior relies on the fact that the global variable is initialized to the empty string and doesnt subsequently
match any value. As a result, the table row template is initially rendered for any returned customer.
As the user makes a selection in the drop-down list, the global currentCountry variable is updated. However, this
action doesnt automatically trigger any refresh on the template as you see in Figure 3. The refresh of the template
must be explicitly commanded in the onchange event handler. Heres a possible way of doing that:
var theDataView = $find("grid");
theDataView.refresh();
The $find function is shorthand for a lookup function that in the Microsoft AJAX library retrieves instances of
components. To use $find (or $get), you must have a ScriptManager control at work and configured in a way that
references the MicrosoftAjax.js core library. Once you have retrieved the DataView instance associated with the
grid template, you just invoke its refresh method. Internally, the method just recompiles the template and updates
the DOM. Note that you dont strictly need to retrieve the DataView instance from the list of registered components.
You can also save the DataView instance to a global variable as you create it upon page loading:
var theDataView = null;
function pageLoad()
{
theDataView = $create(Sys.UI.DataView, ...);
: }
Next, in the onchange handler you just call the refresh method on the global instance:
theDataView.refresh();
In this first example, I used a drop-down list to render the portion of the user interface responsible for triggering
changes on the rest of page. The drop-down list element is particular because it incorporates the logic to raise a
change event when one of its elements is selected.
ASP.NET AJAX, however, provides a more general mechanism to trigger change/notification events that result in
page-specific operations. Lets rework the previous example using a plain hand-made list instead of a drop-down
list.
The sys:command Attribute
The list of countries/regions is now generated using HTML tags for an unordered bulleted list. The template is as
follows:
<fieldset>
<legend><b>Countries</b></legend>
<ul id="listOfCountries" class="sys-template">
<li>
{{ $dataItem }}
</li>
</ul>
</fieldset>
The template is programmatically attached to a DataView control for rendering purposes. Data to fill up the template
is provided via an embedded JavaScript array. The JavaScript array that contains the list of countries is emitted from
the server using the services of the ClientScript object on the Page class. Unlike the previous example, the
Page_Load code doesnt include server-side binding operations:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string[] countries = new string [] {"[All]", "USA", ... "};
string countriesAsString = "[All], USA, ...";
this.ClientScript.RegisterArrayDeclaration(
"theCountries", countriesAsString);
}
}
A second DataView control is instantiated on the client as the page is loaded. Heres the modified code for the
JavaScript pageLoad function, as shown in Figure 5.
Figure 5 JavaScript pageLoad Function
<script language="javascript" type="text/javascript">
function pageLoad()
{
$create(Sys.UI.DataView,
{
autoFetch: true,
dataProvider: "/ajax40/mydataservice.asmx",
fetchOperation: "LookupAllCustomers"
},
{},
{},
$get("grid")
);
$create(Sys.UI.DataView,
{
autoFetch: true,
initialSelectedIndex: 0,
selectedItemClass:"selectedItem",
onCommand: refreshTemplate,
data:theCountries
},
{},
{},
$get("listOfCountries")
);
}
</script>
As you can see, the second DataView used to bind countries/regions to a UL-based template has quite a different
structure than the other.
The first difference is that the data property is used to import data. This is the correct procedure when embedded
data is being used.
When the data source is an array of user-defined objects, you perform binding via the {{expression}} syntax. The
content of the expression is typically the name of a public property exposed by the data item. In this example,
instead, the source of data binding is a plain array of strings. Subsequently, the data item is a string with no public
properties to refer to in the binding expression. In this case, you resort to the following:
<ul>
<li>{{ $dataItem }}</li>
</ul>
The initialSelectedIndex and selectedItemClass properties configure the expected behavior of the DataView as far
the selection of a displayed item is concerned.
The DataView can attach the template the built-in behavior of selection. The item at the position specified by
initialSelectedIndex will be styled according to the CSS class set via the selectedItemClass property. You set
initialSelectedIndex to -1 if you dont want any selection made on first display.
The list that results from the template is a plain UL list and, as such, it doesnt natively incorporate any logic to
handle selection, as you see here:
<ul>
<li>[All]</li>
<li>USA</li>
:
</ul>
By using the sys:command attribute on a HTML element within a template, you instruct the template builder to
dynamically attach a bunch of event handlers to the element, as follows:
<ul id="listOfCountries" class="sys-template">
<li sys:command="select">
{{ $dataItem }}
</li>
</ul>
Figure 6 shows how such modified LI elements show up in the Developer Tools window of Internet Explorer 8. The
sys:command attribute takes a string value that represent the name of the command triggered. The name is actually
up to you. Commands are triggered by clicking on the element. Common commands are select, delete, insert and
update. When the command is triggered, the DataView fires the onCommand event. Heres the code that handles the
onCommand event and refreshes the template:
<script type="text/javascript">
var currentCountry = "";
function refreshTemplate(args)
{
if (args.get_commandName() == "select")
{
// Pick up the currently selected item
currentCountry = args.get_commandSource().innerHTML.trim();

// Refresh
var theDataView = $find("grid");
theDataView.refresh();
}
}
</script>

Figure 6 Event Handlers Dynamically Added as the Effect of sys:command
The same approach can be used for a drop-down list as long as you emit it directly in HTML, as below:
<select>
<option sys:command="select"> {{ $dataItem }} </option>
</select>
Note, though, that a bug prevents the preceding code to work as expected in beta 1. (Figure 7 shows the sample
page in action.)

Figure 7 Commands are Used to Handle Selection
HTML Attributes
In ASP.NET AJAX 4, a special bunch of sys: attributes specify ad hoc bindings for HTML attributes. Functionally
speaking, these attributes are like HTML attributes and you wont notice any different behavior. Figure 8 lists the
namespaced HTML attributes.
All element attributes in a template can be prefixed with the sys: namespace. So whats the ultimate reason for using
mapped attributes? And why are only a few of them are listed in Figure 8?
Figure 8 HTML Mapped Attributes

Often you want to bind to HTML attributes but you dont want to set the attribute itself to your {{...}} binding
expression. From the DOM perspective, the binding expression is simply a value assigned to an attribute and it is
processed as such. This, of course, may have some unpleasant side effects. For example, if you bind to the value
attribute of an input element, or to the content of an element, the binding string may appear for a second to the user
as the page is being loaded. The same happens if you are using binding expressions outside of a template (i.e., live
binding or two-way binding). In addition, there are a bunch of HTML attributesthose listed in Figure 8where
the use of binding expressions may originate unwanted effects. For example, consider the following markup:
<img src="{{ URL }}" />
It triggers a request for the string URL rather than the value of the property URL on the data item.
Other issues you may face include XHTML validation issues and in general wrong attribute resolution by the
browser. If you prefix such critical attributes with the sys namespace, you solve the issue.
So the best practice is to always prefix with the sys namespace any attributes being assigned a binding expression.
The DOM doesnt care about namespaced attributes, so attributes retain their binding expression with no side effects
until it is processed by the template builder.
Namespaced attributes are recommended in client-side rendering, even though they are not certainly mandatory
except in situations where they can save you the effects of wrong HTML parsing.
Whole New World
Templates and data binding open up a whole new world of possibilities to ASP.NET AJAX developers. Next month,
Ill be back to cover various types of binding, including live binding and master/detail views.
Master-Detail Views with the ASP.NET
Ajax Library
Master-Detail Views with the ASP.NET
Ajax Library
Dino Esposito
Download the Code Sample
In the past few columns, I explored a number of data-related features of the upcoming ASP.NET Ajax Library beta,
which is now part of the CodePlex Foundation (CodePlex.org). The journey began last September with a look at
some of the new features in Web Forms and continued with some other stops in the territory of ASP.NET AJAX. In
particular, I touched on client-side templates and data binding,conditional rendering and live binding.
When you think of data-driven Web pages, most of the time what you really have in mind is a master-detail view of
some cross-related data. Master-detail views are ideal for rendering one-to-many relationships, and such
relationships are so common in the real world that a Web platform that doesnt provide an effective set of tools for
that functionality is inadequate.
ASP.NET Web Forms has always provided strong support for data binding and a powerful set of data-source and
data-bound server controls. In Web Forms, server controls do a great job of rendering hierarchies of data using
nearly any possible combination of grids, lists, and drop-down boxes and supporting multiple levels of nesting.
The drawback of the views you get out of Web Forms server controls is not the effectiveness of the rendering, but
the static condition.
Users who navigate within a master-detail view typically switch among master records and drill down into the
details of the records that are of interest. This interaction is the essence of a master-detail view.
In a classic Web Forms scenario, each drill-down operation may trigger a postback. Many postbacksand
subsequent page reloads are not what makes users happy these days.
An alternative exists, but its not free of issues either. It basically consists of preloading any possible data the user
might want to see. The data is then downloaded with the standard page and kept hidden using CSS styles. At the
same time, any handler of user actions is rewritten to unveil hidden content rather than triggering a postback. As you
can see, this is not an easy way to go.
The ASP.NET Ajax Library, in collaboration with jQuery, offers a much more powerful toolset and makes it
possible to write smooth and effective master-detail views that post back asynchronously and only when strictly
needed.
The Hidden Power of the DataView Control
The DataView client control is the fundamental tool for building master-detail views in the ASP.NET Ajax Library.
Combined with the sys-attach feature of the ASP.NET Ajax Library and live binding, the control offers an
unprecedented level of flexibility as far as functionality and layout are concerned. In particular, the DataView
control can serve to generate both the master and detail views.
To arrange a master-detail view with the ASP.NET Ajax Library, you need to follow three basic steps. First, create
the markup for the master and detail views. Second, attach an instance of the DataView control to each view as a
behavior. Finally, use live binding (or just plain data-binding expressions) to populate with fresh data the visual
layout of the detail view. Note that all the templates, binding and component creation can be done both declaratively
and imperatively in code. Lets start with a simple example that serves the purpose of making you familiar with the
approach and the tools available.
Building a Plain Master-Detail View
Heres a simple layout for the master-detail view. It basically consists of two DIV tags. The master DIV contains an
unordered list of items; the detail DIV, instead, contains a child table:
<div id="masterView">
<ul class="sys-template">
...
</ul>
</div>
<div id="detailView">
<table>
<tr>
<td> ... </td>
<td> ... </td>
</tr>
...
</table>
</div>
More often than not, the data to show in an AJAX page is retrieved from the Web server using a Web service, a
Windows Communication Foundation (WCF) service and, of course, any services that can return JavaScript Object
Notation (JSON). The data is commonly sent over the wire as a JSON stream. You can choose to manage the
request to the data source yourself and use your own AJAX framework of choice such as Microsoft AJAX, jQuery
or raw XmlHttpRequest calls.
The DataView control, however, also offers a sort of all-inclusive service. You point it to a remote data provider
such as a Web service, indicate the operation to invoke and list the parameters. Any fetched data is automatically
ready for display anywhere in the HTML page where the DataView is attached. Figure 1shows the markup code
thats necessary for the master view.
Figure 1 The Master View
<div>
<ul class="sys-template" sys:attach="dataview"
id="masterView"
dataview:autofetch="true"
dataview:dataprovider="/ajax40/mydataservice.asmx"
dataview:fetchoperation="LookupCustomers"
dataview:fetchparameters="{{ {query: A} }}"
dataview:selecteditemclass="selecteditem"
dataview:initialselectedindex="0">
<li>
<span sys:command="Select">
<span>{binding CompanyName}</span>
,&nbsp;&nbsp;
<span>{binding Country}</span>
</span>
</li>
</ul>
</div>
The sys:attach attribute attaches a new instance of the DataView control to the UL tag. The code snippet doesnt
show that, but it is necessary that you declare the dataview name and associate it to the JavaScript object that
represents the behavior to attach. Typically, you declare the JavaScript objects you intend to use in the BODY tag:
<body xmlns:sys="javascript:Sys"
xmlns:dataview="javascript:Sys.UI.DataView">
...
</body>
Properties you set declaratively on the automatically created instance of the DataView define the remote call that
will fetch data. In the example, I call the method LookupCustomers on MyDataService.asmx, passing a string
parameter with the value of A.
In addition, the DataView control can accept a few properties specific to the master-detail scenario. The
selectedItemClass property indicates the CSS style to be used for the elements in the item template thats currently
marked as selected. The initialSelectedIndex property refers to the item in the view that must be marked as selected
when the DataView first renders out its data.
The body of the UL tag contains the item template and it binds to fetched data via the ASP.NET Ajax Library live-
binding syntax:
<span>{binding CompanyName}</span>
You could actually use a simpler data-binding expression here:
<span>{{ CompanyName }}</span>
A simple binding expression is enough if you have data to display thats read-only. If your code modifies displayed
data and you need to see changes in real time, then you should opt for live binding. Figure 2shows the detail view.
Figure 2 The Detail View
<div class="sys-template" sys:attach="dataview"
dataview:data="{binding selectedData, source=$masterView}">
<table>
<tr>
<td><b>Contact</b></td>
<td><input id="contact" type="text"
sys:value="{{ContactName}}"/></td>
</tr>
<tr>
<td><b>Address</b></td>
<td><input id="address" type="text"
sys:value="{binding Street}"/></td>
</tr>
<tr>
<td><b>City</b></td>
<td><input id="city" type="text"
sys:value="{binding City}"/></td>
</tr>
<tr>
<td><b>Phone</b></td>
<td><input id="phone" type="text"
sys:value="{binding Phone}"/></td>
</tr>
</table>
</div>
You may have noticed that the value attribute is namespaced. Starting with ASP.NET Ajax Library beta, all
attributes that contain {{expression}} or {binding ...} must include the Sys prefix to not be ignored.
The most interesting part of the code in Figure 2 is the expression assigned to the data property of the DataView:
{binding selectedData, source=$masterView}
The syntax indicates that the values for the elements in the view will come from the object named masterView. The
property that physically provides data to the detail view is selectedData. Needless to say, the object named
masterView will have a property named selectedData, otherwise an error occurs. Figure 3 shows the sample page in
action.
Figure 3 A Master-Detail View Based on the DataView Control

More Control over the Fetch Process
In the first example, I configured the master DataView to support auto-fetching. This means the DataView object is
responsible for triggering the specified fetch operation right after initialization.
This is definitely a good choice for many applications, but some scenarios require more control over the fetch
process. In particular, its often required that you start the fetch following a user action. The next example will
rework the previous code to add a button bar where you choose the first initial of the name of the customers you
want to see listed. Figure 4 shows the final screen.
Figure 4 Starting Data Binding On-Demand

There are many ways to generate a bunch of similar DOM elements on the fly. You can go with the raw DOM API
or perhaps resort to the more abstract programming interface of the Microsoft AJAX library. Or you can opt for
jQuery. Heres a code snippet using the services of the jQuery library to generate a button for each possible initial of
the customer name:

for(var i=0; i<26; i++) {
var btn = $(<input type="button"
onclick="filterQuery(this)" />);
var text = String.fromCharCode(A.charCodeAt(0) + i);
btn.attr("value", text).appendTo("#menuBar").show();
}
The $ function returns a DOM element resulting from the specified markup string. You then set its value property to
an uppercase letter of the alphabet and append the DOM object to a placeholder down the page. The code runs from
within the pageLoad function.
Each input button added in this way is bound to the same click handler. The click handler takes a reference to the
DOM object and updates the master view. Heres the source code of the click handler:
function filterQuery(button) {
// Enables live binding on the internal object that contains
// the current filter
Sys.Observer.setValue(currentQuery, "Selection", button.value);

// Update the master view fillMasterView(currentQuery);
}
Note that, in this example, you need to track the current filter applied to select only a subset of customers. To avoid
pain with the binding, and also to leave room for future enhancement, I opted for a custom object with a single
property. Global to the page, the object is initialized as follows:
var currentQuery = { Selection: "A" };
The current selection is also displayed through a data-bound label in the page. Note the use of the namespace with
the innerHTML attribute of the SPAN tag:
<h3>
Selected customers:
<span sys:innerhtml=
"{binding Selection, source={{currentQuery}}}">
</span>
</h3>
Next, when the user clicks a button to change the selection, you update the Selection property of the object. Note
that the most straightforward code shown here wont really work:
currentQuery.Selection = button.value;
You must enter observable changes only via the setValue method. This is demonstrated in the code snippet shown
earlier using the Sys.Observer.setValue method.
What about the code that fills up the master view programmatically?
To start off, you need to get hold of the instance of the DataView control that operates behind the master view. As
mentioned, the sys-key attribute is only used internally for data-binding purposes. To retrieve a component like
DataView you need to access the list of registered application components as exposed by the $find method of the
Microsoft AJAX library. You use the ID of the root tag as a selector:
var dataViewInstance = Sys.get("$masterView");
In my example, the masterDataView is intended to be the ID of the UL tag marked with the sys-template attribute
that renders the master view:
<div>
<ul class="sys-template"
sys:attach="dataview"
ID="masterDataView"
...>
...
</ul>
</div>
Once you have the DataView instance that populates the master view, adjust the fetch parameters and tell the
DataView to get fresher data. Heres the code you need:
function fillMasterView(query) {
// Retrieves the DataView object being used
var dataViewInstance = Sys.get("$masterDataView");

// DataView fetches fresh data to reflect current selection
var filterString = query.Selection;
dataViewInstance.set_fetchParameters({ query: filterString });
dataViewInstance.fetchData();
}
The fetchData method on the DataView control uses the currently set provider, operation and parameters to place a
remote call and refresh the view with downloaded data.
Adding Caching Capabilities
Lets consider the actual behavior of the page shown in Figure 4. A remote (and asynchronous) request is placed
every time you click on a button to select a subset of customers. Subsequent selections to see details of a particular
customer dont require a roundtrip as long as the data to display is already available for binding.
That mostly depends on what the fetch operation really returns. In my example, the LookupCustomers method is
designed as follows:
public IList<Customer> LookupCustomers(string query);
The properties of the Customer class form the set of data you have ready for binding at no extra cost. If you want to
display, say, the list of orders for each customer, then you can do that without placing an additional request, but only
if the orders are packed with the Customer class and are sent over the wire with the first request.
In a future article, I plan to tackle lazy-loading scenarios and mix that with the AJAX-specific Predictive Fetch
pattern. For now, though, lets simply assume that the data you get out of the DataView fetch operation is enough
for you to craft an effective user interface.
With the solution arranged so far, if you request customers whose name begins with A twice or more, then distinct
requests are placed to get you basically the same set of data. A possible way to improve this aspect is adding some
client-side caching capabilities. The jQuery library comes in handy as it provides an excellent local, in-memory
cache exposed via its core functions.
As one alternative, you can make it so the response is cached by the browser. Then, even though youre issuing
another XmlHttpRequest for the data, the browser doesnt really make a new request for it.
The jQuery Cache API
Seen from the outside, the jQuery cache is nothing more than an initially empty array that gets populated with keys
and values. You can work with the jQuery cache API at two levels: The low-level API is represented by the cache
array property; the higher-level data function provides a bit more abstraction, which saves you from having to check
the array against nullness.
Heres the code to create an entry in the cache and store some data into it:
// Initializes the named cache if it doesnt exist
if (!jQuery.cache["YourNamedCache"])
jQuery.cache["YourNamedCache"] = {};

// Stores a key/value pair into the named cache
jQuery.cache["YourNamedCache"][key] = value;
More precisely, the jQuery cache is organized as a set of named caches grouped under the global cache array.
Reading a value from the cache requires the following code:
var cachedInfo;
if (jQuery.cache["YourNamedCache"])
cachedInfo = jQuery.cache["YourNamedCache"][key];
In this way, you can gain total control over the organization of data within the cache. Each named cache is created
on a strict on-demand basis and no duplication of data ever occurs.
The data method offers a slightly richer programming interface that encapsulates some of the preliminary checks
about the existence of a given named cache. Moreover, the data method allows you to attach the named cache to one
or more DOM elements. The data method offers a basic get/put interface for you to read and write data items to the
cache.
Heres a sample command to assign a given value to a key created in the cache associated with a given DOM
element:
$('#elemID').data(key, value);
The named cache is created on-demand when the code attempts to access or manipulate the content. The library
creates a named cache for the specified element and decides about its name. The name is a progressive number
stored as an expando attribute to the DOM element.
The data method works on the content of a wrapped set. If you define a wrapped set that returns multiple nodes, then
each element gets its own named cache that contains the same data. However, no real data duplication occurs
because the same content is referencednot clonedacross the various cache items.
Consider the following example:
$('div').data('A', fetchedData);
The code attempts to store an entry with a key of A in a named cache for each DIV tag you happen to have in the
page. In this way, you can retrieve or set data from any of the DIV tags you have in the page. For example, the
following two lines of code retrieve the same data:
// Data is actually stored in one place but referenced from many
var data1 = $('div').data('A');

// If the ID references a DIV in the same page,
// the returned data is the same as with the previous code
var data2 = $('#ThisElementIsDiv').data('A');
A common way of using the jQuery cache API is storing data to the DOM element thats really using it. In my
example, the canonical solution would be caching customers in the DIV element bound to the master view.
Putting It All Together
Figure 5 shows the final version of the sample code that retrieves data from a remote service, caches it locally using
jQuery and displays it via a DataView.
Figure 5 Caching Fetched Data
var currentQuery = { Selection: "A" };

function pageLoad() {
// Build the button bar to select customers by initial
for(var i=0; i<26; i++) {
var btn = $('<input type="button"
onclick="filterQuery(this)" />');
var text = String.fromCharCode('A'.charCodeAt(0) + i);
btn.attr("value", text).appendTo("#menuBar").show();
}

// Refresh the list of customers
fillMasterView(currentQuery);
}
function filterQuery(button) {
Sys.Observer.setValue(currentQuery, "Selection", button.value);

// Updates the master view
fillMasterView(currentQuery);
}
function fillMasterView(query) {
// Check cache first: if not, go through the data provider
if (!reloadFromCache(query))
reloadFromSource(query);
}
function reloadFromCache(query) {
// Using the query string as the cache key
var filterString = query.Selection;

// Check the jQuery cache and update
var cachedInfo = $('#viewOfCustomers').data(filterString);
if (typeof (cachedInfo) !== 'undefined') {
var dataViewInstance = Sys.get("$masterView");
dataViewInstance.set_data(cachedInfo);
// Template automatically refreshed
return true;
}
return false;
}
function reloadFromSource(query) {
// Set the query string for the provider
var filterString = query.Selection;

// Tell the DataView to fetch
var dataViewInstance = Sys.get("$masterView");
dataViewInstance.set_fetchParameters({ query: filterString });
dataViewInstance.fetchData(
cacheOnFetchCompletion, null, null, filterString);
}
function cacheOnFetchCompletion(fetchedData, filterString) {
if (fetchedData !== null) {
$('#viewOfCustomers').data(filterString, fetchedData);
}
}
The main refactoring regards the way in which the master view is filled. You first check whether the data is
available in the local cache and proceed with a remote request if no data can be found.
The reloadFromCache method returns a Boolean value to signify that data has been successfully loaded from the
cache. You use the DataViews set_data method to assign the control a new data source. Next, you call the method
refresh to update the view.
You store data in the cache after you retrieve it from the specified provider. The point is that the fetchData method
works asynchronously. This means you cant just place a call to the method get_data right after the method
fetchData returns:
dataViewInstance.set_fetchParameters({ query: filterString });
dataViewInstance.fetchData();
// At this point the method get_data can't retrieve yet
// data for the new selection.
However, the method fetchData accepts some parameters on the command line and all you have to do is pass a
callback, as shown here:
dataViewInstance.fetchData(
cacheOnFetchCompletion, // success callback
null, // failure callback
null, // merge option: append/overwrite
filterString); // context
The first argument indicates the success callback that will be asynchronously invoked after the fetch terminates. The
second argument is the callback to be invoked in case of failure. The third argument refers to the merge option. It is
AppendOnly by default, or it can be OverwriteChanges. Both values are only relevant if you hook up the DataView
to an AdoNetDataContext object. Finally, the fourth argument is the container for any data you want to be received
by the success callback.
Heres the signature of the success callback:
function onSucceededFetch(fetchedData, context)
The first argument the callback receives is the fetched data. The second argument is any context information you
specified through the caller. In my example, the fetch completion callback is the ideal place where to cache fetched
data. The context parameter will be just the query string to cache by.
Data binding is a delicate art and requires a lot of attention and resources to be effective in an AJAX scenario.
ASP.NET Ajax Library offers a lot of tools for crafting a valid data binding and master-detail solution. The list
includes observable collections, live-binding syntax and the DataView control. The ASP.NET Ajax Library beta can
be downloaded from ajax.codeplex.com

Das könnte Ihnen auch gefallen