ASP.NET 2.0 contains a technology called Asynchronous Client Script Callbacks, or simply callbacks for a shortened name.. As the name suggests, this offers the ability for ASP.NET to dir
Trang 1Summar y
In this chapter, you examined several topics related to data communication
❑ XML— XML contains the raw data of a data transfer It is human- and computer-readable in a language-independent format
❑ XSLT— XSLT is used to transform information from one XML format into another
❑ X Path— X Path is used to navigate within an XML/XSLT document
❑ JSON— JSON is a human- and computer-readable data interchange format that is less complex then XML
These topics form an important basis for heterogeneous communications, such as that used in Ajax and between a web client and a web server Knowing how XML, XSLT, and JSON are structured can be very valuable as a basis of a custom Ajax library, for getting data between a web client and a web server, or for being able to diagnose a problem in an existing library
You can find more on the topics discussed in this chapter at the following sites:
❑ Wikipedia—http://en.wikipedia.org/wiki/XML
❑ “SGML Source” by Charles F Goldfarb —www.sgmlsource.com
❑ World Wide Web Consortium (W3C)—www.w3c.org
❑ W3 Schools web site—www.w3schools.org
❑ JSON web site—www.crockford.com/JSON
Trang 2What Is Built into ASP.NET
ASP.NET 2.0 contains an incredible amount of enhancements over ASP.NET 1.0 and 1.1 The ASP.NET team has attempted to address various areas that required improvement in previous versions, and the inclusion of Ajax-style functionality is one of those areas
ASP.NET 2.0 contains a technology called Asynchronous Client Script Callbacks, or simply callbacks
for a shortened name As the name suggests, this offers the ability for ASP.NET to directly support the inclusion of JavaScript code that enables asynchronous calls to the server for processing — that
is, to execute a server method asynchronously from within the browser and have ASP.NET instruct
the browser to execute a JavaScript callback method when the server method completes.
In this chapter, you take a look at:
❑ Server controls included with ASP.NET V2.0 that support asynchronous callback functionality
❑ Enabling your pages to support asynchronous behavior using callbacks in ASP.NET V2.0
❑ Using advanced techniques to develop controls that support asynchronous behavior, using client callbacks
Out-of-the-Box Controls Before you delve into the fundamentals and implementation of these features, it is important to note that some web controls that ship with ASP.NET come with the ability to support callback functionality Specifically, these controls are the:
❑ TreeView
❑ GridView
❑ DetailsView
These controls come with simple boolean properties that enable the use of asynchronous callbacks
in a browser-friendly way, without the need to know or write any JavaScript at all
Trang 3Again, before the chapter gets too technical, have a look at how easy it is to make use of Asynchronous Client Script Callbacks by using some of the controls that support this technology natively
TreeView Control
The TreeViewcontrol allows hierarchical navigation over any datasource A very common use of this control is to act as a navigation control for web sites This is easily achieved by binding the TreeView
control to a SiteMapDataSourcecontrol However, for the purposes of this example you are interested
in the built-in ability to provide asynchronous callback functionality to your applications Examine the following simple ASP.NET page:
Try It Out TreeView Control Utilizing Asynchronous Client Script Callback Support
<%@ Page Language=”C#” AutoEventWireup=”true” CodeFile=”TreeView.aspx.cs”
Inherits=”_Default” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head runat=”server”>
<title>Treeview Asynchronous Example</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:XmlDataSource ID=”XmlDataSource1” runat=”server”
DataFile=”TestXMLFile.xml”>
</asp:XmlDataSource>
<asp:TreeView ID=”TreeView1” runat=”server” DataSourceID=”XmlDataSource1” ExpandDepth=”1”>
</asp:TreeView>
</div>
</form>
</body>
</html>
This page contains a TreeView control and an XmlDataSourcecontrol The XmlDataSourcecontrol provides data from an XML file named TestXMLFile.xml This file has the following contents:
<?xml version=”1.0” encoding=”utf-8” ?>
<root>
<Node1>
<Data1>
<MoreNodes1 />
<MoreNodes2 />
<MoreNodes3 />
<MoreNodes4 />
</Data1>
<Data2 />
</Node1>
<Node2>
<Data3>
Trang 4<More1 />
<More2 />
<More3 />
<More4 />
<More5 />
</Data3>
<Data4 />
</Node2>
<Node3>
<Data5 />
<Data6 />
</Node3>
<Node4>
<Data7 />
<Data8 />
</Node4>
</root>
How It Works
From the example data shown in the preceding block, the nodes Node1, Node2, Node3, and Node4will
be displayed by the TreeViewcontrol When one of these nodes is clicked or selected, the TreeView
requests the subnodes for the selected node from the datasource By default, when the TreeViewcontrol
is dropped onto a page using Visual Studio NET 2005, asynchronous callback functionality is enabled The EnableClientScriptproperty determines this behavior and is set to trueby default The effect that this has is that when a node within the TreeViewis clicked and that node has some subnodes within it that need to be loaded from the datasource, an asynchronous callback is performed to retrieve the data or list of subnodes in this case The user does not see the web page postback to the server If you were to change the preceding web page code so that the markup for the TreeViewcontrol looked like:
<asp:TreeView ID=”TreeView1” runat=”server” DataSourceID=”XmlDataSource1”
ExpandDepth=”1” EnableClientScript=”False”></asp:TreeView>
this would then tell the TreeViewcontrol to not attempt to use client script to retrieve the extra data it
requires Each time a node is expanded in this case, you would notice that the browser performs a post-back Obviously, causing a postback is not as seamless an experience as performing a callback, where no user experience interruption is seen
All the JavaScript required to invoke the necessary asynchronous callback method is controlled via the use of the EnableClientScriptboolean property No JavaScript knowledge or effort is required on the part of the developer
Code samples for this chapter are available for download at http://beginningajax.com.
GridView Control
The GridViewcontrol has its roots in the DataGridcontrol in ASP.NET 1.0/1.1 that was used exten-sively to render tabular data The GridViewcontrol is still used to render tabular data but has some more advanced features and makes extensive use of ASP.NET 2.0 new features and functionality
Trang 5Again, for purposes of this example, you are concerned with the asynchronous behavior that this control provides for you Unlike the TreeViewcontrol, which had asynchronous callback functionality enabled
by default, the GridViewcontrol does not have asynchronous behavior enabled by default You will have a look at why this is the case after examining a simple Try It Out Consider the code that follows
Try It Out GridView Control Utilizing Asynchronous Client Script Callback Support
<%@ Page Language=”C#” AutoEventWireup=”true” CodeFile=”GirdView.aspx.cs”
Inherits=”GridViewAsyncExample_GirdView” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head runat=”server”>
<title>GridView Asynchronous Example</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:GridView ID=”GridView1” runat=”server” AllowPaging=”True”
AutoGenerateColumns=”False”
DataSourceID=”XmlDataSource1” EnableSortingAndPagingCallbacks=”True”>
<Columns>
<asp:BoundField DataField=”BookTitle” HeaderText=”BookTitle”
SortExpression=”BookTitle” />
<asp:BoundField DataField=”Description” HeaderText=”Description” SortExpression=”Description” />
<asp:BoundField DataField=”Comment” HeaderText=”Comment”
SortExpression=”Comment” />
</Columns>
</asp:GridView>
<asp:XmlDataSource ID=”XmlDataSource1” runat=”server”
DataFile=”~/GridViewAsyncExample/XMLFile.xml”>
</asp:XmlDataSource>
</div>
</form>
</body>
</html>
The simple page contains a GridViewcontrol and an XmlDataSource, which the GridViewcontrol uses
to retrieve and manipulate its data to render The data is again stored in an XML file, this time with the following contents:
<?xml version=”1.0” encoding=”utf-8” ?>
<rootNode>
<data1 BookTitle=”Some Interesting stuff” Description=”Lots of interesting stuff” Comment=”Sort of interesting” />
<data1 BookTitle=”More Interesting stuff” Description=”Even more interesting stuff” Comment=”Much more interesting” />
<data1 BookTitle=”Less Interesting stuff” Description=”Less interesting stuff” Comment=”Not as interesting” />
Trang 6<data1 BookTitle=”Big book” Description=”A very big book” Comment=”Too big” />
<data1 BookTitle=”Small Book” Description=”A very small book” Comment=”Too small” />
<data1 BookTitle=”Medium Book” Description=”A medium sized book” Comment=”Just right” />
<data1 BookTitle=”Truthfull stories” Description=”Its the truth!” Comment=”You know its true” />
<data1 BookTitle=”Lies, and why I never tell them” Description=”Its all lies” Comment=”I dont believe any of it” />
<data1 BookTitle=”Fun stories” Description=”Lots of fun” Comment=”Heaps of fun” />
<data1 BookTitle=”Horror stories” Description=”Very scary” Comment=”I was too scared to finish it” />
<data1 BookTitle=”Detective Stories” Description=”Who dunnit?” Comment=”Its a real mystery” />
<data1 BookTitle=”Fantasy stories” Description=”Its a real fantasy” Comment=”Its like living in a dream” />
<data1 BookTitle=”Drama stories” Description=”Dramatic” Comment=”I was riveted” />
<data1 BookTitle=”Action Stories” Description=”Its all about action”
Comment=”Heart pounding” />
</rootNode>
How It Works
Here you have a list of books, their descriptions, and a comment associated with each one The GridView
will render the list of books for the user to browse through By default, sorting and paging is not enabled
on the GridViewcontrol, so all the book entries are displayed on the web page In many cases, paging is enabled to allow a smaller list of content to be displayed at any one time, but also to allow the user to advance that window or page to view more entries within the list In this example, you have enabled paging by setting the AllowPagingproperty of the control to true The GridViewcontrol also contains
aPageSizeproperty that determines how many entries are displayed per page when paging is enabled
By default this is 10, which is what this example uses
When paging is enabled, the GridViewdisplays a paging navigation bar at the bottom of the control to allow the user to select a different page to view By default, when a new page is selected by the user, the
GridViewcauses a postback to occur, so that the data for the next page can be retrieved by the server
In the example, you will note that you set the EnableSortingAndPagingCallbacksproperty to true, and this is what is required to enable asynchronous callbacks for the GridViewcontrol With this
prop-erty enabled, each time the user clicks on the paging navigation bar to view a different page of data, no
postback occurs, but rather an asynchronous callback is executed to perform this work on the server and return the results The new page is then dynamically updated within the GridViewcontrol on the browser
It may now be more apparent why this property is not enabled by default The EnableSortingAnd PagingCalbacksproperty is applicable only if paging and/or sorting is enabled within the GridView
control, and this functionality is not enabled by default Therefore, enabling the EnableSortingAnd PagingCalbacksproperty by default would make no sense
Trang 7DetailsView Control
The DetailsViewcontrol also has very similar functionality to the GridViewcontrol As with the
GridViewcontrol, client-side callback functionality for the DetailsViewcontrol is initially disabled If paging is enabled on the control, then the AllowPagingCallbacksproperty can be set to trueto cause the control to execute its server-side paging functionality asynchronously from the browser
Browser Compatibility
Microsoft has learned from its lessons of the past, and good cross-browser compatibility is one of the main goals of ASP.NET 2.0 All of the samples shown previously work across a majority of fifth
genera-tion browsers, such as Internet Explorer 5.x and above, Mozilla/Netscape 6.x and above, Safari 1.2x, Opera 7.x, and Firefox.
From an application development perspective, it is also very easy to check whether the browser cur-rently accessing your application supports asynchronous client-side callbacks There are two new boolean properties of the Browserobject that are part of the request These are the SupportsCallback
and SupportsXmlHttpproperties, and they indicate if the requesting browser supports asynchronous client callbacks and use of XMLHttpRequestobject, respectively They are part of the property collection
of the Browserobject, which itself is part of the Requestobject, and so can be accessed using the syntax
Request.Browser.SupportsCallbackand Request.Browser.SupportsXmlHttp The properties can be easily examined to determine if the requesting browser supports the desired functionality, as shown in the following Try It Out
Try It Out Determining Client-Side Callback Support Using Server-Side Code
protected void Page_Load(object sender, EventArgs e)
{
if (Request.Browser.SupportsCallback) lblCallbackMsg.Text = “This browser supports client side callbacks.”;
else lblCallbackMsg.Text = “This browser DOES NOT support client side callbacks.”;
if (Request.Browser.SupportsXmlHttp) lblXmlHttpMsg.Text = “This browser supports XmlHttp (receiving XML over HTTP).”;
else lblXmlHttpMsg.Text = “This browser DOES NOT XmlHttp (receiving XML over HTTP).”;
}
How It Works
The Requestobject (which is of type System.Web.HttpRequest) that is available to all pages has a
Browserproperty (which is of type System.Web.HttpBrowserCapabilities) where you access the boolean properties SupportsCallbackand SupportsXmlHttp
Trang 8❑ The SupportsCallbackproperty checks for explicit support of the callback functionality used
by ASP.NET 2.0 and looks for advanced script support such as the ability to invoke scripts upon completion of an asynchronous operation (that is, in callback mode)
❑ The SupportsXmlHttpproperty will return trueonly if the browser supports sending XML content over the HTTP channel
The combination of asynchronous callbacks and the sending of well-formed XML content over HTTP provides a powerful method of communication when dealing with complex data, as you will see later in this chapter
The Framewor k
So, you have seen some of the controls that natively support Asynchronous Client Script Callbacks, and you have seen how you can detect the support of this feature programmatically, but how do you cus-tomize it for use in your own applications and really harness its potential? The answer is twofold
❑ First, there is a newly introduced interface named the ICallbackEventHandlerinterface There is another interface called the ICallbackContainerinterface that indicates that a class can generate its own script to invoke a callback, but it is not the primary interface used when dealing with Asynchronous Client Script Callbacks and will be detailed later in this chapter
❑ Second, in a change from ASP.NET 1.0/1.1, all client scripting functions are now housed in a client script object (which is of type System.Web.UI.ClientScriptManager) that exists as a member within every ASP.NET page object This houses the required functions to support the client-side generation and manipulation of JavaScript code, in particular to work in conjunction with your server-side methods to be called asynchronously
ICallbackEventHandler Interface
The ICallbackEventHandlerinterface is the primary mechanism for enabling pages or controls to participate in the Asynchronous Client Script process By implementing this interface within a control
or page, server code can generate the relevant JavaScript code that allows asynchronous interaction between the client browser and the server This interface has two methods associated with it:
string GetCallbackResult( ); This method returns the result of the callback
event/asynchronous call to the client browser
void RaiseCallbackEvent(string The method that is called asynchronously to handle
eventArgument); the callback event The eventArgumentparameter
contains any data passed in via the callback event/method
Trang 9A web control or web page that intends to provide support for Asynchronous Client Script Callbacks needs to implement this interface and provide implementations for the two interface methods described
in the preceding table
The reason there are two methods is to provide support for asynchronous datasources, a new feature in NET 2.0 An asynchronous datasource will typically initiate a request to get data and then, at some later stage, process the results of the initial call when they become available Having two methods to deal with asynchronous callbacks from the client provides this server-side support for asynchronous datasources These events are central to all callback events This means that if a page implements this interface in order
to act as the recipient for Asynchronous Client Script Callback events, the RaiseCallbackEventmethod will be invoked for all client script callbacks defined within the page, whether one or one hundred This has implications for complex situations where you have multiple ways of triggering a callback method from the client and multiple types of data associated with each event that are passed with each call This will become more apparent as you examine some more complex scenarios that utilize Asynchronous Client Script Callback functionality
Page.ClientScript — System.Web.UI.ClientScriptManager
In order for the server methods of the ICallbackEventHandlerinterface to be invoked on the server,
a callback event must first be triggered by the client, which is the browser Since almost everything dynamic on the browser is performed using JavaScript, you need to provide a method or register a method to perform this function
One of the changes that ASP.NET 2.0 introduced was the centralization of all script-based management functions into a client script management object that is available to all ASP.NET pages This includes client script registration functions that were present in ASP.NET 1.0/1.1 such as the RegisterStartupScript
and RegisterClientScriptBlockmethod These functions now exist as part of the ClientScript
object that is now a member of the Pageobject Previously, in ASP.NET 1.0/1.1, you accessed the client script functions as part of the Pageobject:
private void Page_Load(object sender, System.EventArgs e)
{
Page.RegisterStartupScript(“MyScript”,”<script type=’text/javascript’>alert(‘This is some Javascript’);</script>”);
}
With ASP.NET 2.0, this functionality is now accessed through the ClientScriptobject, which is part
of the Pageobject The ClientScriptobject is of type System.Web.UI.ClientScriptManager The syntax differences are shown in the following example:
protected void Page_Load(object sender, EventArgs e)
{
Page.ClientScript.RegisterStartupScript(this.GetType(), “MyScript”,
“alert(‘This is some Javascript’);”, true);
}
Page.ClientScript.GetCallbackEventReference
In addition to the ASP.NET 1.0/1.1 script management functions, the asynchronous client script manage-ment functions also exist as part of this object Of particular note is the GetCallbackEventReference
Trang 10method This method allows a developer to obtain a reference to the JavaScript method that will trigger the asynchronous callback event The method allows you to specify the name of the variables used to pass
in event data and contextual data, as well as what client-side JavaScript methods to call when the asyn-chronous callback event completes This method will throw an exception if the control or page in which it
is executing does not implement the ICallbackEventHandlerinterface described in the previous section The following code shows an example of using this method:
string js = Page.ClientScript.GetCallbackEventReference(this,
“arg”, “OnServerCallComplete”, “ctx”, true);
The first argument represents the object used to act as the recipient of the callback event The arg param-eter represents the name of the paramparam-eter used to pass the result of the callback event to the client-side JavaScript method The OnServerCallCompleteargument represents the name of the client-side JavaScript method that is called when the asynchronous callback event has completed execution The
ctxparameter represents the name of the context parameter that is passed to the client-side method (in this case OnServerCallComplete) when the asynchronous callback event completes Finally, the true
parameter indicates that the callback event reference returned should be executed in an asynchronous manner The jsstring parameter holds a reference (in actual fact a block of JavaScript code) that is used
to invoke the asynchronous client callback given the parameters specified Given the preceding example, the jsparameter would contain the following:
WebForm_DoCallback(‘ Page’,arg,OnServerCallComplete,ctx,null,true);
Making All the Moving Par ts Wor k Together
So far, you know that in order for a web page or control to participate in, or support, Asynchronous Client Script Callbacks, the ICallbackEventHandlerinterface must be implemented In addition to implementing the two server-based methods of the ICallbackEventHandlerinterface, the page or control must utilize the script management functionality of the ClientScriptobject, which is part of every Pageobject, to register the requisite JavaScript that will trigger the asynchronous callback event This initiates the asynchronous callback process
Once the process has been initiated, client-side methods (JavaScript methods that exist within the web page) need to be supplied to act as the final endpoint where the asynchronous process returns its results for displaying or manipulation by the JavaScript code
This process can be quite hard to grasp and that complexity contributes to the difficulty in being able to develop and debug applications that utilize asynchronous client scripting It is important to be able to fully understand the entire process As you proceed to integrate all the parts of the asynchronous pro-cess, it helps to visualize the flow of functionality This is shown in Figure 6-1, which appears shortly in the chapter Constant reference to this diagram as you proceed through the code samples can help in being able to follow the steps in the process flow
Obtaining a Callback Reference
The first part of this process, as you have already seen, is retrieving a reference to a callback event within the browser to trigger the asynchronous call: