ASP.NET AJAX Development Approach Part 2

Contents

·         1 Introduction

·         2 Type Reflection

·         3 Working With Arrays

·         4 Working with Primitives

·         5 Working With Errors

·         6 Global Methods

·         7 Remote Calls to the Server

·         8 Conclusion

Introduction

If you haven’t read Part 1 of this series, I highly recommend reading that article first, as the concepts from that article are applied into looking at the extensions to the existing object of the ASP.NET AJAX architecture. In the first article, I only touched upon the client architectural concepts. In this article, I’ll look at some of the extensions made available in the ASP.NET AJAX that are also useful for custom development.

ASP.NET AJAX framework Series

· Part 1 Overview of the client portion of the ASP.NET AJAX framework.

· Part 2 Overview of the client portion of the ASP.NET AJAX framework.

· Part 3 Overview of the client portion of the ASP.NET AJAX framework.

· Part 4 Overview of the server portion of the ASP.NET AJAX framework.

· Part 5 Overview of rendering the UI of a control with ASP.NET AJAX.

Type Reflection

As with the .NET framework’s reflection capabilities, JavaScript also has type reflective capabilities. The Object class has two static methods called getType and getTypeName. These methods get information about the type:

Listing 1: Accessing the type in JavaScript

1.var x = new Nucleo.Menus.MenuItem(“Test”);

2.var menuType = Object.getType(x);

3.var menuTypeName = Object.getTypeName(menuType);

Using the type, it’s possible to determine whether an object is a class, interface, namespace, etc. For instance, the following code determines whether the object is a class.

Listing 2: Determining if a type is a class

1.var x = new Nucleo.Menus.MenuItem(“Test”);

2.var menuType = Object.getType(x);

3.alert(Type.isClass(menuType));

Because the ASP.NET AJAX framework allows for inheritance and interfaces, the type class has additional support for determining what an object inherits or implements.

Listing 3: Interface implementation

1.var x = new Nucleo.Menus.MenuItem(“Test”);

2.alert(Nucleo.Menus.MenuItem.inheritsFrom(Sys.Component));

3.var menuType = Object.getType(x);

4.alert(menuType.implementsInterface(Sys.INotifyPropertyChanged);

So how does the ASP.NET AJAX framework know about all of the type information? Every time an object is registered, the registration process adds it to its internal collection of objects. The descriptor exposes the members of the registered classes, interfaces, etc. Therefore, the Type class has built-in capability to reflect upon an object’s given type definition.

In creating a descriptor for the object created in the previous article’s examples (left out from the previous article), the descriptor would look like the code in Figure 4. The descriptor is not defined in the prototype definition, but is its own script block. Define the descriptor before the registration of the class.

Listing 4: The descriptor attribute

01.Nucleo.Menus.MenuItem.descriptor = {

02.    properties:

03.    [

04.        {name:caption, type:String},

05.        {name:text, type:String},

06.        {name:visible, type:Boolean}

07.    ],

08.    methods:

09.    [

10.        {name: toggleVisiblity}

11.    ]

12.    events:

13.    [

14.        {name:visibilityToggled}

15.    ]

16.}

This descriptor defines the members of the MenuItem class, using a collection of dictionaries. Each dictionary specifies a separate member type (property, method, etc.), which also contains a collection of key/value pairs that specify the details of the class. The descriptor contains important information about each of these members. For instance, with properties, the descriptor states whether properties can be null (through the mayBeNull attribute) or if they are read-only (through the readonly attribute), and the property’s type information. These attributes help further restrict the type of input allowed.

Working With Arrays

In its simplest form, an array is represented by the [] notation. This signifies an array, but that doesn’t mean arrays are easy to work with. Some of the extensions to ASP.NET AJAX make working with arrays easy. Below are a few examples of working with arrays:

Listing 5: Working with arrays

01.var arrayData = [];

02.Array.add(arrayData, “Honda”);

03.Array.add(arrayData, “Toyota”);

04.Array.add(arrayData, “Subaru”);

05.alert(Array.contains(arrayData, “Honda”));

06.var index = Array.indexOf(“Toyota”);

07.Array.insert(arrayData, index, “Lexus”);

08.Array.addRange(arrayData, [“Hyundai”, “Acura”, “Suzuki”]);

09.alert(arrayData.length);

10.Array.remove(arrayData, “Suzuki”);

11.Array.removeAt(arrayData, 1);

12.Array.clear(arrayData);

While not the most useful example, it illustrates the new abilities ASP.NET AJAX extensions adds to work manipulate array data.

Working with Primitives

The ASP.NET AJAX extensions add additional capabilities in working with primitives. It extends the String, Number, Boolean, Date, etc. types to include additional functionality. Let’s look at some of the new string methods first. Below is an example of working with strings:

Listing 6: Processing text

01.function processString(text)

02.{

03.    //There is also trimStart and trimEnd options too

04.    var input = text.trim();

05.    if (input.startsWith(“\’”))

06.        input = input.substring(1, input.length – 1);

07.    if (input.endsWith(“\’”))

08.        input = input.substring(0, input.length – 2);

09.    if (input.indexOf(“{0}”) > -1)

10.        input = input.format(“Welcome {0}!”, input);

11.    return input;

12.}

Not all of the methods above are extended in the ASP.NET AJAX library; however, there are some useful additions. I personally enjoy the ability to use format strings through the format method. The format method is very handy in the .NET framework to insert data into prefabricated text, and now it’s available client-side.

In addition, the extensions add the startsWith and endsWith method for checking the start and end of the text for specific characters. There are several options for trimming text, either by using trim(), trimStart(), or trimEnd(), which trim the start, the end, or both the start and end of the string.

Because data is often textual in nature, for integer data to be used property, it has to be of the right type. Some of the components in the AJAX control toolkit validate their parameters for correctness. In order to convert textual data to numerical form, use the following approaches:

Listing 7: Parsing Numbers

1.var number1 = Number.parseInvariant(text); //culture agnostic

2.alert(number1);

3.var number2 = Number.parseLocale(text); //culture specific

4.alert(number2);

Depending on whether your needs are a number for a specific culture or an invariant number (culture-agnostic), these two methods help convert textual data to a number. If, for some reason, the number isn’t valid, the constant NaN is returned. For culture-specific formatting to work, set the ScriptManager’s EnableScriptGlobalization to true, as well as configure the <globalization culture=”auto”> element in the configuration file.

Boolean values have a similar utility for parsing, though culture specific functionality isn’t needed, therefore the method name is “parse” accordingly. Because the process is similar to above, I’ve left it out of the discussion.

Working With Errors

ASP.NET AJAX components have the ability to throw errors whenever the conditions aren’t correct. For instance, if a parameter value is out of range or of the wrong type, errors can be thrown that are returned to the caller, similar to how the .NET framework works. Errors were in the JavaScript library; however, the ASP.NET AJAX extensions added several specific options for throwing errors.

For instance, to validate incoming data, the following could be used to ensure the input is correct (which isn’t possible in the example below):

Listing 8: Throwing errors

01.function processText(text)

02.{

03.    if (text == null || text === undefined)

04.        throw Error.argumentNull(“text”, “No value provided.”);

05.    if (text.length == 0)

06.        throw Error.argument(“text”, “Empty string”);

07.    if (text.length > 50)

08.        throw Error.argumentOutOfRange(“text”, text, “range issue”);

09.    if (text == “invalid”)

10.        throw Error.invalidOperation(“Invalid operation”);

11.    if (text == “not done”)

12.        throw Error.notImplemented();

13.    var err = Error.create(“Generic Error”);

14.    throw err;

15.}

Errors are a normal way to express that a condition isn’t right. The above example doesn’t properly show that (throwing an exception in every case), but there are many options available when throwing errors. It’s possible to create a custom exception of your own, and append it to the Error object.

JavaScript also has the ability to catch errors using a try/catch block like C#, which already exists in the JavaScript framework.

Global Methods

There are a new set of global methods available with the ASP.NET AJAX extensions. These global methods are shortcuts for performing common operations. For instance, the $get method is a shortcut for document.getElementById and retrieves a reference to the HTML element in the page. The $find method, however, is a shortcut method for finding a specific component by its ID. This is a highly useful command to access the class for an AJAX control or extender. For instance, take a look at the following code snippet:

Listing 9: Accessing a TabContainer AJAX control using $find

01.<script language=”javascript”>

02.    function pageLoad()

03.    {

04.        var tabs = $find(“<%= tabContainer.ClientID %>”);

05.        if (tabs.get_tabs().length > 1)

06.            tabs.set_activeTabIndex(1);

07.    }   

08.</script>

09...

10.<asp:TabContainer id=”tabContainer” runat=”server”>

11.    ..

12.</asp:TabContainer>

The $find method now contains a reference to the client class; every AJAX server control or extender has a client counterpart. The $find method returns a reference to that client component which has its own ID value that matches the ID of the control. Depending on where in the lifecycle $find is called, a null reference may be returned.

Remote Calls to the Server

ASP.NET AJAX also has the ability to connect to a server and return data brought back from a web service or a static page method. The key to making this work is defining the service locally. What that means is the remote call has to be to the local web server; otherwise, an exception will be thrown. This is not an error; rather, it’s a feature. It’s designed this way for security purposes.

Making a call to the web server is done through the Sys.Net.WebServiceProxy class. Under the scenes, the class uses a Sys.Net.WebRequest object to connect to the web service/page method. If you are familiar with this object in .NET server framework, the System.Net.WebRequest object performs the work of connecting to a web resource, returning a WebResponse with the response from the requested system. The WebRequest/WebResponse objects have been used in examples of screen-scraping, where the contents of an HTML page are downloaded to the program and data is extracted from it.

I’m going to illustrate using the page method approach. As I said before, the WebServiceProxy can call a method defined in the page class. The requirements of this method are that it is defined as static, and that it is decorated with the WebMethod attribute, as shown below:

Listing 10: Page method used in web service call

1.[WebMethod]

2.public static string GetCurrentDate()

3.{

4.    return DateTime.Now.ToString();

5.}

The date returned from the web service method is passed to a span element in the page. Take a look at the following definition.

Listing 11: ASPX that consumes page method

01.<script language="javascript" type="text/javascript">

02.    function pageLoad()

03.    {

04.        var wsProxy = new Sys.Net.WebServiceProxy();

05.        wsProxy.set_timeout(0);

06.        var label = $get("displayText");

07.        var request = wsProxy._invoke("http://localhost/testpage.aspx"

08.            "GetCurrentDate", false, {}, onSuccess, onFailure, label);

09.    }

10.    function onSuccess(result, userContext, methodName)

11.    {

12.        userContext.innerText = result;

13.    }

14.    function onFailure(result, userContext, methodName)

15.    {

16.        userContext.innerText = "Error";

17.    }

18.</script>

19.<span id="displayText"></span>

The _invoke method performs the actual work. Here the web service connects to the static page method on a page using the local web server. The _invoke method also takes the name of the method (GetCurrentDate), whether the request uses HTTP get, the parameters involved ({} meaning no parameters in this case; otherwise, a key/value pair is provided using key:value format), and the callback/context information.

If the web service works successfully, the date will be displayed in the span; otherwise, the text error is displayed in the span.

Conclusion

This article, part 2 of the series, looks at some of the additional abilities that ASP.NET AJAX gives you, such as the use of descriptors, type information, and new objects like Error, Array, String, Number, etc. It also looked into making web service calls to a static page method. All of these features are keys to developing a rich AJAX user experience

.

 

posted on 2010-12-01 14:16  ALLENWANG  阅读(341)  评论(0编辑  收藏  举报

导航