Tải bản đầy đủ (.pdf) (15 trang)

Beginning Ajax with ASP.NET- P20 doc

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (432.81 KB, 15 trang )

}
function ComplexScriptCompleteCallback(result)
{
alert(“Value: “ + result);
}
</script>
<input type=”button” value=”Click for Complex DataType”
onclick=”ComplexDataTypeCall();” />
<atlas:ScriptManager ID=”Script1” runat=”server”>
<Services>
<atlas:ServiceReference Path=”ComplexWebService.asmx” />
</Services>
</atlas:ScriptManager>
<div>
</div>
</form>
<script type=”text/xml-script”>
<page xmlns:script=” /><references>
</references>
<components>
</components>
</page>
</script>
</body>
</html>
The code for the complex data type is:
public class cComplexCustomerType
{
public cComplexCustomerType()
{
}


private string _Name;
private string _Address;
public string Name
{
get { return _Name; }
set { _Name = value;}
}
public string Address
{
get { return _Address; }
set { _Address = value; }
}
}
The code for the web service is:
[WebMethod]
public cComplexCustomerType AcceptComplexDataType(cComplexCustomerType
objComplexCustomerType)
261
Atlas Client Script
13_78544X ch10.qxp 7/18/06 3:17 PM Page 261
{
return (objComplexCustomerType);
}
In this example code, the web service accepts the custom business object and then returns the value.
There is nothing that would stop the web service from using the properties of the business object that is
passed or the web service from returning a string as opposed to the custom business object.
Interrogation of the custom object returns interesting information. The following code will generate the
results in Figure 10-5. This figure shows that the
Name and Address properties are available along with
an added member — the

__serverType property. This property defines the type on the server.
function ComplexScriptCompleteCallback(result)
{
var str = “”;
debug.dump(result);
for(prop in result)
str += “Member: “ + prop + “\r\n”;
alert(str);
}
Figure 10-5
A call to
debug.dump() on the returned result object produces the output in Figure 10-6. The debug
.dump()
method displays the contents of an object in Atlas. This method will be discussed more later in
this chapter.
Figure 10-6
262
Chapter 10
13_78544X ch10.qxp 7/18/06 3:17 PM Page 262
Caching Web Services
The data returned from a web service may be cached. This can be helpful in situations where data may
not be time critical (for example, a web service that returns the weather forecast for a given location).
This is performed in .NET by setting a value on the
CacheDuration of the WebMethod() attribute. As
you may have previously done when working with web services, Atlas makes it possible to call a cached
web service and get the results of a web service call. Depending on the data and the time that is required
to perform the calculation, the time saved by caching may be significant when factored over thousands
of possible users.
Take a look at some code and the result. In this example, you are just going to display the time of each
call. On the first call, both times that are returned will be the same. Subsequent calls will result in the

current time being updated and the cached time being the same, while the cached time is not updated
until the cache duration is over.
This is the code for an
.aspx page:
<%@ Page Language=”C#” AutoEventWireup=”true” CodeFile=”CachedWebService.aspx.cs”
Inherits=”CachedWebService” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“ /><html xmlns=” >
<head runat=”server”>
<title>Untitled Page</title>
</head>
<body>
<form id=”form1” runat=”server”>
<input type=”button” id=”btnGetServerTime” value=”Get Server Time”
onclick=”GetServerTime();” />
<script language=”javascript”>
function GetServerTime()
{
CachingWebService.GetServerCachedTime(DisplayServerCachedTime);
CachingWebService.GetServerCurrentTime(DisplayServerCurrentTime);
}
function DisplayServerCurrentTime(result)
{
var ctrl = document.getElementById(“NewTime”);
ctrl.innerText = result;
}
function DisplayServerCachedTime(result)
{
var ctrl = document.getElementById(“StartTime”);
ctrl.innerText = result;

}
</script>
<atlas:ScriptManager ID=”Script1” runat=”server”>
<Services>
<atlas:ServiceReference Path=”CachingWebService.asmx”
GenerateProxy=”true” />
</Services>
</atlas:ScriptManager>
<br />
Start Call:
263
Atlas Client Script
13_78544X ch10.qxp 7/18/06 3:17 PM Page 263
<div id=”StartTime”></div>
<br />
New Time:
<div id=”NewTime”>
</div>
<script type=”text/xml-script”>
<page xmlns:script=” /><references>
</references>
<components>
</components>
</page>
</script>
</form>
</body>
</html>
In the preceding code, on a button click, two remote calls are made out to the server—a call to the
GetServerCachedTime method and one to the GetServerCurrentTime method. The GetServer

CachedTime
method on the server returns the current server time when it is called the first time. The
result of this call is cached in server memory. Subsequent calls are returned the cached result for the next
100 seconds, at which point the next request will generate a new time and a new entry in the server cache.
As a result, calls to
GetServercurrentTime() will result in the current time of the server being
returned while calls to
GetServerCachedTime() will result in a value that is up to 100 seconds old.
The following is the code for a web service:
[WebMethod(CacheDuration = 100)]
public DateTime GetServerCachedTime()
{
return(DateTime.Now.ToUniversalTime());
}
[WebMethod]
public DateTime GetServerCurrentTime()
{
return (DateTime.Now.ToUniversalTime());
}
Atlas uses UTC encoding for dates and time. This may create confusion for you if you don’t remember
it. Personally, my system is set with the time of GMT – 5. As a result, the times that were coming back
were 5 hours off.
Figure 10-7 shows the results of multiple calls to the cached and noncached web services.
In Figure 10-7, you will notice the two different time values. This shows that calling the cached web ser-
vice returns the cached value and the noncached version returns the current value of the
DateTime.Now
object.
264
Chapter 10
13_78544X ch10.qxp 7/18/06 3:17 PM Page 264

Figure 10-7
Exposing Web Services from a Web Form
All of the examples you’ve explored to this point in this chapter have used a dedicated web service. It is
also possible to have a web service that is exposed within an internal page of a web application. On the
surface, it appears that there is no real advantage to this. However, there are two advantages to using
web services that are exposed by a web form. These are:
❑ The page and web service are deployed together. There are fewer files to deploy and fewer
things that can go wrong.
❑ While not having been announced as this is being written, it appears that Microsoft will be adding
some special functionality that will be available only to a web service that is called within a web
form. Given the early status of Atlas, more information will come out about this in the future.
This next example calls back to a web service on the same
.aspx page.
The code for the web page is:
<%@ Page Language=”C#” AutoEventWireup=”true” CodeFile=”InternalWebService.aspx.cs”
Inherits=”InternalWebService” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“ /><html xmlns=” >
<head runat=”server”>
<title>Internal Web Service Page</title>
</head>
<body>
<atlas:ScriptManager ID=”Script1” runat=”server”>
</atlas:ScriptManager>
<form id=”form1” runat=”server”>
<div>
<input type=”button” id=”btn” value=”Call Internal Web Service”
onclick=”CallInternalWebService()” />
265
Atlas Client Script

13_78544X ch10.qxp 7/18/06 3:17 PM Page 265
<script language=”javascript”>
function CallInternalWebService()
{
PageMethods.CallInternalWebService(InternalCallBack);
}
function InternalCallBack(result)
{
alert(result);
}
</script>
</div>
</form>
</body>
</html>
In the preceding code, note that the calling convention is not Class.MethodName(), but PageMethods
.MethodName()
. PageMethods is a special class that is used to call the methods internal to a page.
The code-behind file is shown below. Note the addition of the
System.Web.Services namespace,
which is not typically specified in a code-beside or aspx page. The method displayed in the following
merely returns a string as an example; however, any number of datatypes can be returned, just like a
regular web service and the other examples.
using System.Web.Services;

[WebMethod]
public string CallInternalWebService()
{
return (“Internal Web Service Called.”);
}

The result of this is shown in Figure 10-8.
Figure 10-8
266
Chapter 10
13_78544X ch10.qxp 7/18/06 3:17 PM Page 266
Atlas Extensions to JavaScript
Atlas allows for the creation of rich client-side applications that run within the browser. To facilitate the
creation of these applications, Atlas has created a set of extensions to the type system in JavaScript.
These extensions provide many of the features of the .NET type system to the client-side web browser
environment. These extensions include namespaces, inheritance, interfaces, enums, support for strings,
and arrays.
Language Enhancements
JavaScript has been around as a language since the early betas of the Netscape Navigator 2.0 web
browser appeared in late 1995 to early 1996. Since then, there have been numerous enhancements to the
JavaScript language. The latest version of the language is version 1.6. With the shipment of the .NET
Framework, Microsoft has released a framework that contains a set of base classes that have features
across various languages, including Visual Basic, C#, and JavaScript when running native and server-
side applications. Into this, steps Atlas. Atlas provides a set of enhancements on top of JavaScript as it
runs in the web browser. The next sections look at these enhancements and extensions.
Controls
Atlas provides a set of controls, classes, and objects that may be used programmatically in JavaScript.
Object
The Object class is a client version of the .NET System.Object class. The only method that it imple-
ments is the
getType(obj) method. This method will return the type of the specified object.
Array
The Array class is similar in concept to the .NET System.Collections.ArrayList() class. It has
several interesting members such as
length, push(), and pop(). A small example is
var ary = new Array();

ary.push(47);
alert(“length: “ + ary.length);
In this short example, the user is presented with an alert box with a length of 1.
Date
The Date class is conceptually similar to a client web browser version of the .NET System.DateTime class.
The
Date object supports a set of methods similar to the Date() class in .NET. There are methods to create
a date, get various parts of a date, and set the parts of a date. For a quick example, it is possible to create a
date:
var dt = new Date();
dt.setFullYear(2006, 03, 26);
dt.setHours(10, 12, 13, 5);
alert(“Date: “ + dt.toString());
In the preceding example code, the date that is created is March 26, 2006, 10 hours, 12 minutes, 13 sec-
onds, and 5 milliseconds. The resulting date is then displayed to the user in an
alert() window.
267
Atlas Client Script
13_78544X ch10.qxp 7/18/06 3:17 PM Page 267
Number
The Number class contains several methods. There are several methods to parse the content of the num-
ber as well as convert it to a string, get the exponential value, and perform other operations.
Boolean
The Boolean class is used for parsing traditional boolean values. It implements several methods for
creating a boolean. If the passed value is a string and would return as boolean, the boolean value is
returned.
String
The String class is a client web browser version of the .NET String class. The String() class imple-
ments some of the methods that are similar to the
String() class in .NET. Some of the more interesting

members of the Atlas
String() class are:

indexOf() — The indexOf(string, startingindex) returns the value of the starting loca-
tion of the specified string when at the
startingindex location.

lastIndexOf() — The lastIndexOf(string, startingindex) returns the value of the
starting location of the last time the specified string is found.

substring() — The substring(start, end) returns the substring from the starting location
to the ending location.

substr() — The substr(start, length) returns the substring from the starting location of
the specified length.

toLowerCase() — The lowercase version of the string is returned.

toUpperCase() — The uppercase version of the string is returned.
RegExp
The RegExp class is a client web browser version of the .NET Regular Expression library. The Atlas
RegExp class supports the .parse(value) method.
Built-In Namespaces
Atlas comes with a number of built-in namespaces and classes for managing data, HTTP communica-
tion, user interface design, and other things. These are in the
Sys.* namespaces. The next sections look
at several of the namespaces and their associated classes.
Sys.Net.WebRequest
The Sys.Net namespace provides a set of classes to facilitate HTTP communications between the client
and the web server. Though other classes exist within the name, the one we are going to look at is the

WebRequest class.
The
Sys.Net.WebRequest class provides support for making HTTP requests. The following sample
code, for example, makes a web request.
var request;
268
Chapter 10
13_78544X ch10.qxp 7/18/06 3:17 PM Page 268
function MakeCall()
{
request = new Sys.Net.WebRequest();
var url = Sys.Net.WebRequest.createUrl(“PageThatIsCalled.aspx”, null);
request.set_url(url);
request.completed.add(RequestCompleted);
request.timeout.add(RequestTimeOut);
request.invoke();
}
function RequestCompleted(objSender, evArgs)
{
if (blRun == true )
{
var obj = objSender.get_webRequest();
var objWR = objSender.get_data();
debug.dump(objWR, “Web Content:”, true);
}
}
Figure 10-9 shows the output of the preceding code. In this example, the content from the called page is
contained within the
debug.dump statement as expected. In the preceding example, a call is made out to
a web page in the same directory, and its contents are displayed.

Figure 10-9
Sys.Data.DataColumn
The Sys.Data namespace provides a set of classes that are essentially client-side versions of the similar
classes in the
System.Data namespace of the .NET Framework. This namespace provides support
for classes called
DataColumn, DataRow, DataTable, DataView, DataFilter, DataSource, and
PropertyFilter.
269
Atlas Client Script
13_78544X ch10.qxp 7/18/06 3:17 PM Page 269
The Sys.Data.DataColumn class allows for the interrogation of column information within a
Sys.Data.DataTable class. The DataColumn exposes the following members. These members
will be useful for processing datasets and data tables that are returned from a web service.
Members Description
get_columnName() This method will retrieve the column name of a specific column.
get_dataType() This method will retrieve the datatype of the column.
get_defaultValue() This method will retrieve the default value of a column.
dispose() This method will dispose() of the object and perform any nec-
essary cleanup.
The following example code will interrogate a returned dataset. The first thing that is necessary is to get
a datatable. This is performed by calling the
result.getItem(0) method.
function MethodReturn(result)
{
var i = 0;
var str = “”;
var strColInfo = “”;
var strReturn = “<br />”;
for (prop in result)

str += “Property: “ + prop + “\r\n”;
alert(str);
var tbl1 = result.getItem(0);
for(i = 0; i < tbl1.get_columns().length; i++)
{
strColInfo += tbl1.get_columns()[i].get_columnName() + “:” +
tbl1.get_columns()[i].get_dataType() + strReturn;
}
document.getElementById(“ColInfo”).innerHTML = strColInfo
}
In the preceding code, a web service returns a dataset in the result variable to the MethodReturn()
JavaScript function. There is a for() loop that returns the properties/members of the result object. This
is then presented to the user in an
alert() box. This alert() box is only for information’s sake. The
first table in the dataset is pulled out of the dataset by calling
result.getItem(0). Within the first
table, the next
for() loop iterates through the columns returned, gets the datatype, and creates a string,
and after the
for() loop exits, the data is presented to the user.
Figure 10-10 shows the output of the preceding code. One thing to notice is that the
get_dataType()
returns information.
270
Chapter 10
13_78544X ch10.qxp 7/18/06 3:17 PM Page 270
Figure 10-10
Sys.Data.DataTable
The Sys.Data.DataTable class provides all information for integration with the System.Data
.DataTable

. The DataTable exposes the following members that may be of interest.
Members Description
get_columns() This method will return an array of DataColumns within the DataTable.
get_keys() This method will return an array of DataColumns that contain various
keys within the DataTable.
get_isDirty() This method will return a boolean indicating whether or not updates have
been made on the DataTable object.
get_length() This method will return the number of rows within the DataTable.
add() The add method will allow the addition of a DataRow.
clear() The clear() method will clear the contents of the DataTable.
getChanges() The getChanges() method will provide a set of DataRows that have
changed.
getColumn() The getColumn() method will provide the specified column.
getItem() The getItem() method will provide the specified row. This method is
very important.
remove() The remove() will remove the specified row.
dispose() Performs the standard dispose mechanism.
271
Atlas Client Script
13_78544X ch10.qxp 7/18/06 3:17 PM Page 271
The following is some code that will iterate through the rows of a DataTable:
function MethodReturn(result)
{
var i = 0;
var str = “”;
var strRowsInfo = “”;
var strReturn = “<br />”;
//get a datatable
var tbl1 = result.getItem(0);
for(i = 0; i < tbl1.get_length(); i++)

{
//tbl1.getItem(i) will return the ith DataRow
//getProperty(“Column Name”) will return the column value from a DataRow
strRowsInfo += tbl1.getItem(i).getProperty(“ProjectName”) + strReturn;
}
document.getElementById(“RowInfo”).innerHTML = strRowsInfo;
}
In the preceding code, a dataset is returned. The first datatable is obtained by the call to getItem(0). Then
the
DataRows are iterated. This is done by the for() loop. To get at the value of a column in a specific row,
we use the
getProperty(“ProjectName”) method. This method returns the value from the column
ProjectName in the example. Some example output from the preceding code is shown in Figure 10-11.
Figure 10-11
Sys.Data.DataRow
The Sys.Data.DataRow class is the Atlas version of the System.Data.DataRow class. The DataRow
has a set of properties and is designed for accessing a single row of data from a data table. For example,
the
DataRow.getProperty(“ColumnName”) method shown in the previous code will return the value
of that specific column in that
DataRow.
272
Chapter 10
13_78544X ch10.qxp 7/18/06 3:17 PM Page 272
For more information about this namespace and classes and others, you can check out http://atlas
.asp.net/
and for updated documentation from Microsoft along
with the site for this book
.
Registering Namespaces and Classes in Atlas

JavaScript is a fairly simple scripting language. When implemented in a web browser environment, it
lacks many features that are common to modern programming languages. As a result, it is necessary for
Atlas to add functionality to create namespaces, classes, and other items that are familiar to developers
who use modern programming languages. There are several different mechanisms to register classes in
Atlas.
Type.registerNameSpace
A namespace is used to group common functionality together. The Type.registerNameSpace()
method is used to register a namespace in Atlas-enabled JavaScript. The proper call for this method
is as follows.
Type.registerNameSpace(‘NamespaceName’);
In this example, NamespaceName is a string representing the name of the namespace.
NamespaceName.ClassName.registerClass
A class is a set of methods and data that provide a specific piece of functionality. Atlas provides a mecha-
nism to register classes. This is performed within the following call.
NamespaceName.ClassName.registerClass(‘NamespaceName.ClassName’, ParentClass,
InterfaceImplemented);
In this example, the NamespaceName.ClassName is a string representing the name of the class. If the
class that is being registered is to inherit from another class, that parent class is passed as the second
parameter. The final parameter is any interface that may be implemented within the class.
Take note that not all of the parameters are required.
NamespaceName.ClassName.registerAbstractClass
An abstract class is one that contains methods that are not actually implemented within the class. Also,
abstract classes cannot be instantiated — their only purpose is to be used as a model for child classes.
The definition is performed by the following code.
NamespaceName.ClassName.registerAbstractClass(‘NamespaceName.ClassName’,
ParentClass, InterfaceImplemented);
In this example, the NamespaceName.ClassName is a string representing the name of the class. If the
class that is being registered is to inherit from another class, that parent class is passed as the second
parameter. The final parameter is any interface that may be implemented within the class.
Take note that not all of the parameters are required.

273
Atlas Client Script
13_78544X ch10.qxp 7/18/06 3:17 PM Page 273
NamespaceName.ClassName.registerSealedClass
A sealed class is one that may not be inherited from. The definition is performed by the following code.
NamespaceName.ClassName.registerSealedClass(‘NamespaceName.ClassName’, ParentClass,
InterfaceImplemented);
In this example, the NamespaceName.ClassName is a string representing the name of the class. If the
class that is being registered is to inherit from another class, that parent class is passed as the second
parameter. The final parameter is any interface that may be implemented within the class.
Take note that not all of the parameters are required.
InterfaceName.registerInterface
An interface essentially states that a class implements a specific set of methods. The interface is defined
by registering an interface. This is performed by the following code.
InterfaceName.registerInterface(‘InterfaceName’);
In this example, the InterfaceName is merely a string representing the name of the interface that is to
be implemented. Note that by convention all interfaces are named with a capital “I” prefix.
NamespaceName.ClassName.registerBaseMethod
If a class is going to be specifically overridden in a base class, the method must be marked in the base
class. This is performed by the following code:
NamespaceName.ClassName.registerBaseMethod(class, “methodname”);
For example, the class will most likely be defined as the current class in JavaScript (this). A good candi-
date for the method name is the
dispose method.
Namespaces and Classes
Namespaces allow for the grouping of classes, methods, objects, and data that are closely related. Atlas
includes functionality on the
Type object to add namespaces and classes. These are accomplished
through the
Type.registerNamespace and Class.registerClass methods.

Try It Out Adding a Namespace and Class through Atlas
The steps necessary to add a namespace and class to JavaScript through Atlas are:
1. The atlas:ScriptManager must be added to an .aspx page. The script manager will add the
appropriate script references.
<atlas:ScriptManager runat=”server” ID=”scriptManager” />
2. Register a namespace. This is performed through the Type.registerNamespace method. In
this example, the string
NamespaceName is just an example name for a namespace:
Type.registerNamespace(“NamespaceName”);
274
Chapter 10
13_78544X ch10.qxp 7/18/06 3:17 PM Page 274
3. Define the contents of a class:
ExampleNamespace.cComplexCustomerType = function(Name, Address)
{
var _Name = Name;
var _Address = Address;
this.getName = function() {
return _Name;
}
this.setName = function(val){
_Name = val;
}
this.getAddress = function() {
return _Address;
}
this.setAddress = function(val){
_Address = val;
}
this.Dispose = function(){

alert(“disposing component with Customer Name:” + this.getName() + “ @ “ +
this.getAddress());
}
}
4. Register the class:
Type.registerClass(“ExampleNamespace.cComplexCustomerType”, Web.IDisposible);
5. To add standard methods, such as toString(), to a class, use the prototype member:
ExampleNamespace.cComplexCustomerType.prototype.toString = function(){
return this.getName() + “ at “ + this.getAddress();
}
Adding an item through the prototype member results in sharing of the member between
instances. Sharing of objects defined with the prototype member must be avoided or unusual
results may occur. Conceptually, this is similar to static/shared members in .NET.
Now that a class has been created a program can use the class. The following code will use the class and
display the
.toString() value of the customer object:
var objCust = new ExampleNamespace.cComplexCustomerType(“Acme”, “Wileyville,
USA”);
alert(objCust.toString());
Figure 10-12 shows the result.
Figure 10-12
275
Atlas Client Script
13_78544X ch10.qxp 7/18/06 3:17 PM Page 275

×