You are on page 1of 17

Microsoft Virtual Labs

ASP.NET AJAX: Part 2 - Client-


Side Data Binding
ASP.NET AJAX: Part 2 - Client-Side Data Binding

Table of Contents
ASP.NET AJAX: Part 2 - Client-Side Data Binding ................................................................. 1
Exercise 1 Build a Data Service ....................................................................................................................................2
Exercise 2 Create a ListView Template ........................................................................................................................6
Exercise 3 Add DataSource and ListView Controls ......................................................................................................9
Summary...................................................................................................................................................................... 15
ASP.NET AJAX: Part 2 - Client-Side Data Binding

ASP.NET AJAX: Part 2 - Client-Side Data


Binding
After completing this lab, you will be better able to:
Objectives  Create a data service for use with client-side data binding
 Use DataSource controls to provide a client-side interface to data services
 Use ListView controls to perform client-side data-binding
 Declare controls, bindings, and other objects using xml-script

Estimated Time to 90 Minutes


Complete This Lab

Page 1 of 15
ASP.NET AJAX: Part 2 - Client-Side Data Binding

Exercise 1
Build a Data Service

Scenario
In this exercise, you’ll build the server-side infrastructure to support a shopping cart page by building a data service
to serve as the data source for client-side data binding.
Note: If you prefer to Copy & Paste code instead of typing, you can use the version of the lab manual included on
the Desktop of the Virtual Machine.

Tasks Detailed Steps


1. Open the Web site Note: Logon to the server using following credentials:
Username: John
Password: Pass@word1
a. Open Visual Studio 2005. You will see “ASP.NET AJAX Lab 2” in the list of
Recent Projects. Open this Project.
Note: If you are notified that “Administrator permissions are recommended for
running Visual Studio 2005 SP1”, click Continue. This lab does not require
Administrator permissions.
b. You will need to open Site.master and add the following markup just after the
opening <form> tag to declare a ScriptManager control in the site’s master page:

<asp:ScriptManager ID="MasterScriptManager"
runat="server">
</asp:ScriptManager>
c. Then save your changes and close Site.master.
Note: Pages that use ASP.NET AJAX must declare an instance of ScriptManager.
Among other things, the ScriptManager control ensures that the core JavaScript files
comprising the Microsoft AJAX Library get downloaded to the client.
2. Create the shopping a. Use Visual Studio’s Website->Add New Item command to add a Web service
cart Web service named ShoppingCart.asmx to the Web site.

Page 2 of 15
ASP.NET AJAX: Part 2 - Client-Side Data Binding
Tasks Detailed Steps

b. Replace the contents of ShoppingCart.cs (found in App_Code) with this:

using System;
using System.Web;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.Web.Preview.Services;
using System.Web.Script.Services;

[ScriptService]
public class ShoppingCart : DataService
{
public ShoppingCart()
{
}

[WebMethod(EnableSession = true)]
[DataObjectMethod(DataObjectMethodType.Select)]
public ShoppingCartItem[] GetCartItems()
{
// Pull shopping cart cookie
HttpCookie cookie =
HttpContext.Current.Request.Cookies["ShopCartID"];

// Call shopping cart data service to retrieve


cart items for this user
ShoppingCartItem[] cartItems = new
ShoppingCartItem[0];
if (cookie != null)

Page 3 of 15
ASP.NET AJAX: Part 2 - Client-Side Data Binding
Tasks Detailed Steps
{
// Pull the user's cart
cartItems =
new
ShoppingCartDataService().GetCartItems(cookie.Value).CartI
tems;
}
return cartItems;
}

[WebMethod(EnableSession = true)]
[DataObjectMethod(DataObjectMethodType.Update)]
public void UpdateCart(ShoppingCartItem cartItem)
{
// Pull shopping cart cookie
HttpCookie cookie =
HttpContext.Current.Request.Cookies["ShopCartID"];

// Call shopping cart data service to save this


cart item
if (cookie != null)
{
new
ShoppingCartDataService().UpdateCart(cookie.Value,
cartItem);
}
}
}
Note: The Web service you just created has two methods: GetCartItems, which returns
shopping cart items to the client, and UpdateCart, which accepts data from the client
and updates the shopping cart data store. Note the [DataObjectMethod] attributes
identifying one method as the “Select” method and the other as the “Update” method.
Also note the [ScriptService] attribute decorating the Web service itself. This attribute
is required if the Web service is to be called by an ASP.NET AJAX client.
Note: Also observe that the Web service derives from DataService rather than
WebService. DataService is defined in the Microsoft.Web.Preview.Services
namespace. It identifies a Web service as a “data service”—that is, one that contains
specially designated methods for performing selects, inserts, updates, and deletes.
Note: The infrastructure that the Web service relies on has already been provided for
you. ShoppingCartDataService, which you’ll find in the App_Code folder, is a data
component used to access shopping cart data. ShoppingCartDataService, in turn, uses
the XmlCartProvider class (found in App_Code/Providers) to access the data store.
The data store is nothing more than an XML file (App_Data/ShoppingCart.xml), but
because of the provider-based architecture used here, you could easily modify the site
to store shopping cart data in a database instead.
Note: The products in ShoppingCart.xml are REAL products from Burton, makers of
fine snowboards and snowboarding accessories and generally wild and crazy people.
Visit their Web site at http://www.burton.com to see the products first-hand. In fact,
the markup we’ll use to display the shopping cart items is patterned after the markup
in the real Burton Web site.
c. Test the Web service by launching ShoppingCart.asmx in your browser. Use the
autogenerated test harness to invoke the service’s GetCartItems method. Verify
that the output resembles that pictured below.

Page 4 of 15
ASP.NET AJAX: Part 2 - Client-Side Data Binding
Tasks Detailed Steps

d. Close your browser and return to Visual Studio.

Page 5 of 15
ASP.NET AJAX: Part 2 - Client-Side Data Binding

Exercise 2
Create a ListView Template

Scenario
In this exercise, you’ll create a template that an ASP.NET AJAX ListView control can use to format the markup that
it generates on the client. The template is contained in a hidden DIV to prevent it from being seen. The hidden DIV
is accompanied by an empty DIV that marks the location on the page where the ListView will ultimately position
the markup that it generates.

Tasks Detailed Steps


1. Link to the shopping a. Although a partially completed version of ShoppingCart.aspx is already present
cart page from in the Burton Starter Kit, the “Shopping Cart” link in the master page points to
Site.master the site’s coming-soon page (ComingSoon.aspx). You’ll need to edit that link to
point to ShoppingCart.aspx. Begin by opening Site.master for editing.
b. Find the HyperLink control whose ID is “ShopOnlineHyperLink”.
c. Change the HyperLink’s NavigateUrl property to “~/ShoppingCart.aspx”.
d. Save your changes to Site.master.
2. Import a. Open ShoppingCart.aspx in Visual Studio.
PreviewScript.js b. Import PreviewScript.js by adding the following ScriptManagerProxy
declaration inside the <asp:Content> element:

<asp:ScriptManagerProxy
ID="ShoppingCartScriptManagerProxy" runat="server">
<Scripts>
<asp:ScriptReference Name="PreviewScript.js"
Assembly="Microsoft.Web.Preview" />
</Scripts>
</asp:ScriptManagerProxy>
Note: ScriptManagerProxy controls allow you to add script and service references to
ScriptManager controls declared in master pages. The ScriptReference element in this
example downloads the core ASP.NET AJAX CTP file (PreviewScript.js), which
contains the ListView and DataSource control used in this lab.
3. Create a placeholder c. Near the top of the ShoppingCart.aspx, you’ll find a comment that reads “Add
for ListView output the cart markup here.” Replace the comment with the following DIV:

<div id="cartResults">
</div>
Note: This DIV, while empty at the moment, will be filled with content when the
ListView renders out its data.
4. Create an item a. Underneath the DIV you just added is a DIV with the ID “cartLayoutTemplate.”
template and a This is the template the ListView control will use to format the markup it
separator template generates. Look through the template and find the comment that reads “Add the
TBODY element here.” Replace the comment with an empty TBODY element:

<tbody id="cartResults_itemTemplateParent">
</tbody>

Page 6 of 15
ASP.NET AJAX: Part 2 - Client-Side Data Binding
Tasks Detailed Steps
b. Now add the following markup to the TBODY element to define an item template:

<tr id="cartResults_itemTemplate">
<td class="col6Shopping">
<span class="blank">&nbsp;</span>
<input type="checkbox" id="ItemRemoved" />
</td>
<td class="col1Shopping">
<a id="ItemLink" href="">
<img style="float: left; padding: 0 10px 10px 0;
border: none"
id="ItemImage" src="" alt="" />
<br />
<span id="ItemName" class="productAttr"></span>
</a>
<br />
<span id="ItemDesc"
class="cartShortDescription"></span>
</td>
<td class="col2Shopping">
<span class="required">*</span>
<input type="text" class="inputShopQty" id="ItemQty"
value="1" size="2" />
</td>
<td class="col3Shopping">
<span id="ItemPrice"></span>
</td>
<td class="col4Shopping">
<span id="QtyTotal"></span>
</td>
</tr>
Note: If you’re familiar with ASP.NET data-binding controls, the item template you
just created is analogous to an <ItemTemplate> in a Repeater control.
c. Like ASP.NET Repeater controls, ASP.NET AJAX ListView controls support
separator templates—templates that define the markup inserted between items the
control renders out. Following the markup you added in the previous step, add this
TR element to define the format of item separators:

<tr id="cartResults_itemSeparator" class="greenDotted560">


<td colspan="5"></td>
</tr>
5. Create an “empty a. You now have a template in place for shopping cart items. But what happens if the
cart” template cart is empty and there are no items? ListView controls allow you to define
“empty” templates that are analogous to the ASP.NET GridView control’s
<EmptyDataTemplate>. To add an empty template, locate the closing DIV tag for
the “cartLayoutTemplate” DIV (it’s marked with a comment that reads “Add the
empty cart markup here”). Replace the comment with the following DIV:

<div id="cartResults_emptyTemplate">
<span class="col1Shopping">
There are currently no items in your shopping cart!
</span>

Page 7 of 15
ASP.NET AJAX: Part 2 - Client-Side Data Binding
Tasks Detailed Steps
</div>
Note: That’s it! Your templates are set up and ready to go.

Page 8 of 15
ASP.NET AJAX: Part 2 - Client-Side Data Binding

Exercise 3
Add DataSource and ListView Controls

Scenario
You have nearly all the pieces in place to create a stunning client-side data-bound shopping cart page. In the final
exercise, you’ll use xml-script to declare a ListView control and a DataSource control and wire the two together.
You’ll also add some JavaScript to lend a helping hand.
Note: xml-script is a declarative markup language featured in the ASP.NET AJAX January Futures CTP. It allows
you to declare instances of controls using XML elements such as <listView> and <dataSource>. It also lets you
initialize control properties, bind data sources to data consumers, handle control events, and more. xml-script is
often more intuitive than JavaScript for programming templated controls.

Tasks Detailed Steps


1. Add xml-script a. Add the following xml-script block to ShoppingCart.aspx just above the
</asp:Content> tag at the end of the file:

<script type="text/xml-script">
<page xmlns:script="http://schemas.microsoft.com/xml-
script/2005" >
<components>
</components>
</page>
</script>
b. Add the following element to the xml-script block (between the <components> and
</components> tags) to declare a DataSource control that connects to
ShoppingCart.asmx on the server:

<dataSource id="cartDataSource"
serviceURL="ShoppingCart.asmx" autoLoad="true"
dataAvailable="tallyTotal" />
Note: There are three items of note here. First, for security reasons, the serviceURL
attribute must refer to a Web service in the same domain as the application itself.
Second, autoLoad=“true” tells the DataSource control to automatically call the data
service’s select method when the page loads. Without that, you’d have to write code to
make the initial call yourself. Finally, the DataSource control fires a dataAvailable
event after the data is downloaded. The dataAvailable attribute registers a handler
named tallyTotal for that event. tallyTotal, which you haven’t written yet, sums the
prices of the items in the shopping cart.
c. Now declare a ListView control right after the DataSource control:

<listView id="cartResults"

itemTemplateParentElementId="cartResults_itemTemplateParen
t">
</listView>
Note: The id and itemTemplateParentElementId attributes refer to elements in the
markup. The id attribute identifies the DIV that serves as a placeholder for the
ListView control’s output; itemTemplateParentElementId identifies the element that is

Page 9 of 15
ASP.NET AJAX: Part 2 - Client-Side Data Binding
Tasks Detailed Steps
the parent of the item template.
d. Add the following markup to the body of the ListView control—that is, between
the <listView> and </listView> tags:

<bindings>
<binding dataContext="cartDataSource" dataPath="data"
property="data" />
</bindings>
<layoutTemplate>
<template layoutElement="cartLayoutTemplate" />
</layoutTemplate>
<separatorTemplate>
<template layoutElement="cartResults_itemSeparator" />
</separatorTemplate>
<emptyTemplate>
<template layoutElement="cartResults_emptyTemplate" />
</emptyTemplate>
<itemTemplate>
<template layoutElement="cartResults_itemTemplate">
<checkBox id="ItemRemoved">
<bindings>
<binding dataPath="ItemRemoved" property="checked"
direction="InOut" />
</bindings>
</checkBox>
<image id="ItemImage">
<bindings>
<binding dataPath="ItemImage" property="imageURL"
/>
<binding dataPath="ItemDesc"
property="alternateText" />
</bindings>
</image>
<hyperLink id="ItemLink">
<bindings>
<binding dataPath="ItemLink"
property="navigateURL" />
</bindings>
</hyperLink>
<label id="ItemName">
<bindings>
<binding dataPath="ItemName" property="text" />
</bindings>
</label>
<textBox id="ItemQty">
<bindings>
<binding dataPath="ItemQty" property="text"
direction="InOut" />
</bindings>
</textBox>
<label id="ItemPrice">
<bindings>
<binding dataPath="ItemPrice" property="text" />

Page 10 of 15
ASP.NET AJAX: Part 2 - Client-Side Data Binding
Tasks Detailed Steps
</bindings>
</label>
<label id="ItemDesc">
<bindings>
<binding dataPath="ItemDesc" property="text" />
</bindings>
</label>
<label id="QtyTotal">
<bindings>
<binding dataPath="QtyTotal" property="text" />
</bindings>
</label>
</template>
</itemTemplate>
Note: There’s a lot going on here, but it’s not as scary as it might seem. The first
<binding> element binds the ListView to the DataSource. <itemTemplate>,
<separatorTemplate>, and other elements identify the HTML templates that in turn
define how items, separators, and other content is rendered by the ListView. Inside the
<itemTemplate>, elements such as <image>, <checkBox>, and <label> declare
instances of controls featured in the ASP.NET AJAX January Futures CTP. These
controls wrap the DOM elements with the same IDs. Finally, the <binding> elements
bind properties of the controls to properties of the data source. If you look at the
ShoppingCartItem class in App_Code/CartItems.cs, you’ll see that shopping cart items
implement the properties referenced in the bindings: ItemLink, ItemName, and so on.
2. Add JavaScript a. The xml-script you just wrote does the bulk of the work, but it needs a helping
hand from JavaScript to sum up the prices of the items in the shopping cart and
bind them to a SPAN element, to update the shopping cart when the Update button
is clicked, and to reset the cart to its original state when “Reset Cart” is clicked. To
that end, add the following script block to the page before or after the xml-script
block:

<script type="text/javascript">
function tallyTotal(result)
{
var o = result.get_data();
var c = result.get_rowCount();
var i;
var total = 0;
if (c > 0)
{
for (i = 0; i < c; i++)
total = total +

parseFloat(o.getRow(i).get_rowObject().QtyTotal.substring(
1));
$get('CartTotal').innerText =
formatDollars(total);
}
}

function UpdateCart()
{
var cartDataSource =

Page 11 of 15
ASP.NET AJAX: Part 2 - Client-Side Data Binding
Tasks Detailed Steps
Sys.Application.findComponent('cartDataSource');
if (cartDataSource.get_isDirtyAndReady())
cartDataSource.save();
}

function formatDollars(dollars)
{
var strDollar = (dollars + "");
if (strDollar.charAt(0) == "$")
strDollar = strDollar.substring(1);

var amt = parseFloat(strDollar);


if (isNaN(amt))
return strDollar;

amt = Math.round(100 * amt);


var prefix = "$";
if (amt < 0)
{
prefix = "-" + prefix;
amt = -amt;
}

var retAmt;
if (amt < 10)
retAmt = prefix + "00" + amt;
else if (amt < 100)
retAmt = prefix + "0" + amt;
else
retAmt = prefix + amt;

retAmt = retAmt.substring(0, retAmt.length - 2) +


"." +
retAmt.substring(retAmt.length - 2,
retAmt.length);

return retAmt;
}

function OnReset()
{
PageMethods.ResetCart(ResetCartComplete);
}

function ResetCartComplete()
{
var cartDataSource =
Sys.Application.findComponent('cartDataSource');
cartDataSource.load();
}
</script>
b. Take a moment to examine the code you just entered. The UpdateCart function is
called when the user clicks the page’s Update button. It calls a function in the
Microsoft AJAX Library (“findComponent”) to retrieve a reference to the

Page 12 of 15
ASP.NET AJAX: Part 2 - Client-Side Data Binding
Tasks Detailed Steps
DataSource object declared in xml-script. Then it calls the DataSource’s save
function, which in turn calls the update method of the data service.
Note: Also of interest is the OnReset function, which is called when the “Reset Cart”
button is clicked. It fires off a call to a special type of Web method called a page
method. A page method is a static Web method that’s implemented in an ASPX instead
of an ASMX. Page methods are called using the PageMethods.MethodName syntax.
You haven’t written the ResetCart page method yet, but you’ll take care of that in the
next two steps.
c. Open ShoppingCart.aspx.cs and add the following fields to the code-behind
class:

protected const string OriginalDatabaseFilename =


"~/App_Data/ShoppingCart.original.xml";
protected const string DatabaseFilename =
"~/App_Data/ShoppingCart.xml";
d. Now add the ResetCart page method to the code-behind class:

[WebMethod]
public static void ResetCart()
{
// Open our original "database."
System.Xml.XmlDocument cartDB = new
System.Xml.XmlDocument();

cartDB.Load(HttpContext.Current.Server.MapPath(OriginalDat
abaseFilename));

// Save as our new "database."

cartDB.Save(HttpContext.Current.Server.MapPath(DatabaseFil
ename));
}
Note: ResetCart resets the shopping cart by overwriting the contents of
ShoppingCart.xml with the contents of ShoppingCart.original.xml.
Note: Because ResetCart overwrites the contents of ShoppingCart.xml on the server,
the account that the application runs as requires write access to the Web site’s
App_Data folder. If you’re running the site in Visual Studio using the built-in
ASP.NET Development Server, then your account (the person you’re logged in as)
requires that write permission. If you were running the site in IIS instead, you’d need
to grant write access to whatever account the application is configured to run as
(typically, ASPNET, Network Service, or a designated domain account).
e. Open Site.master and add an EnablePageMethods=“true” attribute to the
ScriptManager control:

<asp:ScriptManager ID="MasterScriptManager"
EnablePageMethods="true"
runat="server">
</asp:ScriptManager>
Note: Page methods are disabled by default. You enable them by setting the
ScriptManager control’s EnablePageMethods property to true.
3. Test the results a. Launch ShoppingCart.aspx in your browser. Verify that the resulting page

Page 13 of 15
ASP.NET AJAX: Part 2 - Client-Side Data Binding
Tasks Detailed Steps
resembles the one below (although you may only see one shopping cart item
displayed at a time because the virtual environment is unable to reference the script
schema at http://schemas.microsoft.com/xml-script/2005):

b. Check one of the “Remove” boxes and click the Update button. Verify that the
item disappears from the page and that the subtotal at the bottom of the page is
updated, too.
c. Click the “Reset Cart” button and verify that the item you deleted reappears—that
is, that the shopping cart is restored to its original state.
d. Close your browser and return to Visual Studio.

Page 14 of 15
ASP.NET AJAX: Part 2 - Client-Side Data Binding

Summary
Here’s a recap of what you learned in this lab:
• How to create a data service for use with client-side data binding
• How to use DataSource controls to provide a client-side interface to data services
• How to use ListView controls to perform client-side data-binding
• How to declare controls, bindings, and other objects using xml-script
ListView controls also support sorting, paging, and other operations. But that’s a topic for another day!

Page 15 of 15

You might also like