Professional Documents
Culture Documents
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
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.
<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
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"];
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"];
Page 4 of 15
ASP.NET AJAX: Part 2 - Client-Side Data Binding
Tasks Detailed Steps
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.
<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"> </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:
<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.
<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 retAmt;
if (amt < 10)
retAmt = prefix + "00" + amt;
else if (amt < 100)
retAmt = prefix + "0" + amt;
else
retAmt = prefix + amt;
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:
[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));
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