Published: 01 Dec 2006
By: Alessandro Gallo

ASP.NET AJAX provides a way to instantiate client side types using a declarative programming model ala ASP.NET.

Overview

ASP.NET AJAX provides a way to instantiate client side types using a declarative programming model ala ASP.NET. One of the simplest examples of declarative code is the following, which displays a message after the page is loaded:

<%@ Page %>  
<!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>Hello XML-script</title> 
  </head> 
  <body>     
  <form id="form1" 

runat="server">     
  <asp:ScriptManager ID="TheScriptManager" runat="server">         
   <Scripts>             
    <asp:ScriptReference 
      Assembly="Microsoft.Web.Preview"
Name="Microsoft.Web.Resources.ScriptLibrary.PreviewScript.js" />            
   </Scripts>     
  </asp:ScriptManager>      
  <script type="text/xml-script">         
    <page xmlns="http://schemas.microsoft.com/xml-script/2005">
      <components>             
        <application load="page_load" />          
      </components>         
    </page>     
  </script>      
  <script type="text/javascript">     
  <!--         
  function page_load(sender, e) 
  {             
    alert("Hello World!");         
  }     
  //-->     
  </script>     
  </form> 
  </body> 
</html> 

Note that in order to use the xml-script feature you must download the Futures CTP package from the Microsoft Ajax website and add a reference to the PreviewScript.js file contained in the Microsoft.Web.Preview assembly.

A block of declarative code is always embedded into a script tag with the type attribute set to text/xml-script. The declarative code in the example isn't difficult to understand; we have a root page element that encapsulates a components element, which is the standard form of a generic xml-script block.

Inside the components element we find an application node with the load attribute set to the name of the function declared in the JavaScript code block. The load attribute is parsed as an event name and its value is parsed as the reference to a function that will be added to the corresponding list of event handlers. Since the application element is mapped to the Sys.Application instance, the result is that page_load() will be called when Sys.Application raises its load event.

How is this possible? The answer is that the declarative code is based on a mapping between xml elements and the methods, properties and events exposed by an ASP.NET AJAX class. This kind of mapping exists for every class that exposes a type descriptor, and every class that exposes a type descriptor can be used in declarative code.

Type descriptors

A type descriptor is an object that describes the properties, methods and events exposed by a class. Every class that intends to provide a descriptor should implement the ITypeDescriptorProvider interface, which defines a single method called getDescriptor(); this method must return the type descriptor associated to the class. The prototype of the ITypeDescriptorProvider interface is declared as follows:

Sys.Preview.ITypeDescriptorProvider.prototype = {     
  getDescriptor: Sys$Preview$ITypeDescriptorProvider$getDescriptor 
} 

Another way of exposing a type descriptor (that eliminates the dependency from Sys.Preview) is adding a descriptor expando to the class. If we browse the PreviewScript.js file (that contains part of the classes in the Sys.Preview namespace) we can find many descriptors exposed in this way. For example, the following code shows the descriptor of the Sys.Preview.Button class:

Sys.Preview.UI.Button.descriptor = {     
  properties: [ { name: 'command', type: String },                  
                { name: 'argument', type: String } ],     
  events: [ { name: 'click' } ] 
} 

A type descriptor is an object (typically represented with a JavaScript dictionary, that is a comma-separated list of attribute and value pairs enclosed in curly braces, as in { name: "value" }) that contains the following attributes:

  • properties, holds an array of property descriptors
  • events, holds an array of event descriptors
  • methods, holds an array of method descriptors

Each array also contains a set of descriptors, but this time their purpose is to describe a particular property, event or method rather than the type. For example, let's examine the descriptor contained in the array of events:

{ name : 'click' } 

This descriptor simply tells that the Button class exposes an event named click. The array of properties contains two descriptors:

{ name: 'command', type: String } 
{ name: 'argument', type: String }

The first descriptor describes a property called command that is of type String. The second descriptor tells us that the Button class exposes a property of type string, called argument.

Type descriptors enable reflection of client side types and are independent from xml-script. Nonetheless, the xml-script parser uses them extensively to map properties, methods and events to XML elements in declarative code.

By examining a type descriptor, we are able to write the declarative code needed to create an instance of that type, without knowing anything of how xml-script works. Compare the following XML with the type descriptor of the Button class:

<button id="myButton" command="save" click="myButton_click" /> 

In the above XML, the name of the class (Sys.Preview.UI.Button) is mapped to the name of the element (button), while properties are mapped to attributes; the value of each attribute will be assigned to the corresponding property. The click event is also mapped to an attribute, and its value is the name of a JavaScript function called myButton_click, which is in charge of handling the event.

Where does the id property come from? The Button class inherits from Sys.Component, and the id property is inherited from this class. If you search for the type descriptor of Sys.Component in the PreviewScript.js file, you'll find also the description of the id property:

Sys.Component.descriptor = {     
  properties: [ {name: 'dataContext', type: Object},                  
                {name: 'id', type: String},
                {name: 'isInitialized', type: Boolean, readOnly: true},
                {name: 'isUpdating', type: Boolean, readOnly: true} ],     
  events: [ {name: 'propertyChanged'} ] 
} 

Describing a method also requires providing the description of its parameters. The following code shows the methods attribute extracted from the type descriptor exposed by the Sys.Preview.Net.ServiceMethodRequest class:

methods: [ {name: 'invoke', params: [ {name: 'userContext', type: Object} ] } ] 

In this case, the class is exposing a single method called invoke (as told by the name attribute of the method descriptor). This method accepts a single parameter called userContext, which is of type Object. Parameters are described in the array stored in the params attribute, and each parameter has an associated parameter descriptor.

Conclusions

In this tutorial we've seen a basic example of an ASP.NET page that contains a block of declarative code; then, we introduced type descriptors and learned how to read them. Type descriptors provide reflection for client side types in the Microsoft Ajax Library. They are also used to support the declarative programming model, which allows instantiating client side types by using declarative xml syntax.

In the next tutorial we'll continue to examine the mapping between type descriptors and XML elements.

References

Xml-script tutorial Part 1
Xml-script tutorial Part 2
Xml-script tutorial Part 3
Xml-script tutorial Part 4

About Alessandro Gallo

Alessandro "Garbin" Gallo is a Microsoft MVP in the Visual ASP/ASP.NET category and a .NET developer/consultant. He is a contributor for the Ajax Control Toolkit project, owned by Microsoft. Alessandro won the Grand Prize at the "Mash-it-up with ASP.NET AJAX" contest held by Micr...

This author has published 23 articles on DotNetSlackers. View other articles or the complete profile here.

Other articles in this category


ASP.NET Ajax Grid and Pager
Learn how to create a custom Ajax Grid and Pager with the Microsoft ASP.NET AJAX platform.
JSON-Enabled WCF Services in ASP.NET 3.5
Dino Esposito overviews the integration between WCF and AJAX
Using jQuery with ASP .NET
A brief introduction to jQuery and ways in which we can integrate it into ASP .NET
ASP.NET AJAX Control Development
An in depth guide to developing controls with the ASP.NET AJAX
ASP.NET Ajax Web Service
Sharing some of the Common Issues of ASP.NET Ajax Web Services.

You might also be interested in the following related blog posts


Issue 48 - DotNetNuke 5 Introduction and Open Web Studio Tutorials read more
Issue 49 - DotNetNuke 5 Skin Packaging, Spam and SQL, OWS read more
GiveCamps Get a new Sponsor read more
Issue 47 - DotNetNuke Nav Menu and Open Web Studio Tutorials read more
More On The CodePlex Foundation read more
Custom Panels in Silverlight/WPF Part 1: MeasureOverride read more
Introducing SharePoint 2010 Training at U2U read more
Private Extension Methods read more
Assembly-Free jQuery in SharePoint Sites Using the SmartTools jQueryLoader read more
Scenarios for WS-Passive and OpenID read more
Top
 
 
 

Please login to rate or to leave a comment.

Product Spotlight