Excerpt from ASP.NET AJAX Programmer's Reference
Developing Custom ASP.NET AJAX Client Controls
by Dr. Shahram Khosravi
An ASP.NET AJAX client control is an ASP.NET AJAX client component that directly or indirectly derives from the Control
base class. You can think of an ASP.NET AJAX client control as an ASP.NET AJAX representation of a specific DOM element on a page.
The ASP.NET AJAX client controls essentially emulate their corresponding ASP.NET server controls. Most basic ASP.NET server controls, such as Label
and Image
, are ASP.NET representations of DOM elements. These representations enable you to program against the underlying DOM elements using the ASP.NET/.NET Framework. In other words, these representations enable you to treat DOM elements as .NET objects.
The ASP.NET AJAX client controls play a similar role in the client-side programming. These controls are the ASP.NET AJAX representations of DOM elements, allowing you to program against these elements using the ASP.NET AJAX Framework. In other words, these representations enable you to treat DOM elements as ASP.NET AJAX objects.
Every ASP.NET AJAX client control emulates its corresponding ASP.NET server control as much as possible. As such, they expose similar methods and properties as their server counterparts.
The ASP.NET AJAX client-side framework includes with a Sys.Preview
namespace defined as follows:
Type.registerNamespace('Sys.Preview');
The Sys.Preview
namespace contains a UI
namespace defined as follows:
Type.registerNamespace('Sys.Preview.UI');
The Sys.Preview.UI
namespace contains several client controls that directly or indirectly derive from the ASP.NET AJAX Control
base class. The following sections walk you through the code for these client controls to help you gain the skills you need to develop your own custom client controls. You'll also take a look at the code for Web pages that use these client controls.
Label Client Control
The ASP.NET AJAX Label
client control is the ASP.NET AJAX representation of the <span>
HTML element. The Label
client control derives from the Control
base class and extends its functionality to add support for two new properties named htmlEncode
and text
. The following sections discuss the members of the Label
client control.
Constructor
Listing 1 presents the implementation of the constructor of the Label
client control. Note that this constructor takes a single argument, which references the DOM span
element that the Label
control represents.
Listing 1: The Constructor of the Label Client Control
Sys.Preview.UI.Label = function Sys$Preview$UI$Label(associatedElement) { Sys.Preview.UI.Label.initializeBase(this, [associatedElement]); } Sys.Preview.UI.Label.registerClass('Sys.Preview.UI.Label',Sys.UI.Control);
This constructor calls the initializeBase
method to invoke the constructor of its base class—Control
—passing in the reference to the DOM element that the Label
control represents.
htmlEncode
The Label
client control exposes a getter method named get_htmlEncode
and a setter method named set_htmlEncode
that respectively get and set the value of the htmlEncode
Boolean property of the control, as shown in Listing 2.
Listing 2: The Getter and Setter Methods of the html Encode Property
function Sys$Preview$UI$Label$get_htmlEncode() { return this._htmlEncode; } function Sys$Preview$UI$Label$set_htmlEncode(value) { this._htmlEncode = value; }
text
Listing 3 presents the implementation of the Label
control's get_text
getter method, which returns the value of the text
property of the control.
Listing 3: The get_text Getter Method of the Label Control
function Sys$Preview$UI$Label$get_text() { var element = this.get_element(); if (this._htmlEncode) return element.innerText; else return element.innerHTML; }
This method first calls the get_element
method to return a reference to the DOM element that the Label
control represents:
var element = this.get_element();
The Label
control inherits the get_element
method from its base class— Control.
Next, the get_text
method checks whether the value of the htmlEncode
property is set to true
. If so, it returns the value of the innerText
property of the DOM element that the Label
control represents:
if (this._htmlEncode) return element.innerText;
If not, it returns the value of the innerHTML
property of the DOM element that the Label
control represents:
else return element.innerHTML;
Listing 4 presents the implementation of the set_text
method of the Label
control.
Listing 4: The set_text Method of the Label Control
function Sys$Preview$UI$Label$set_text(value) { if (!value) value=""; var element = this.get_element(); if (this._htmlEncode) { if (element.innerText !== value) { element.innerText = value; this.raisePropertyChanged('text'); } } else { if (element.innerHTML !== value) { element.innerHTML = value; this.raisePropertyChanged('text'); } } }
This method first calls the get_element
method of its base class to return a reference to the DOM element that the Label
control represents:
var element = this.get_element();
Next, it checks whether the value of the Label
control's htmlEncode
property has been set to true
. If so, it assigns the new value to the innerText
property of the DOM element and calls the raisePropertyChanged method to raise the propertyChanged event:
element.innerText = value; this.raisePropertyChanged('text');
The Label
control inherits the raisePropertyChanged
method from the Component
base class. If the htmlEncode
property has been set to false, get_text
assigns the new value to the innerHTML
property of the DOM element and calls the raisePropertyChanged
method to raise the propertyChanged
event.
The get_text
and set_text
methods of the Label
control constitute convenient wrappers around the innerText
and innerHTML
properties of the DOM element that the control represents.
If you're wondering how the get_text
and set_text
methods work in a browser such as Firefox that does not support the innerText
property, the answer lies in the Mozilla compatibility layer of the ASP.NET AJAX client-side framework, which includes the logic that adds the support for this property. Refer to the PreviewScripts.js
JavaScript file for more information on the Mozilla compatibility layer.
prototype
As Listing 5 shows the get_htmlEncode,
set_htmlEncode,
get_text,
and set_text
methods of the Label
client control are directly defined on the prototype
property of the control. This means that these methods are instance methods and must be invoked on the instances of the Label
control class, not the class itself.
Listing 5: The prototype Property of the Label Control
Sys.Preview.UI.Label.prototype = { _htmlEncode: false, get_htmlEncode: Sys$Preview$UI$Label$get_htmlEncode, set_htmlEncode: Sys$Preview$UI$Label$set_htmlEncode, get_text: Sys$Preview$UI$Label$get_text, set_text: Sys$Preview$UI$Label$set_text }
descriptor
Every component, including the Label
control, must expose a property named descriptor
that references an object literal describing the members of the component. The ASP.NET AJAX client-side framework includes a class named TypeDescriptor
that uses the descriptor
property of a component to discover its members. In other words, the descriptor
property of a component contains metadata about the type of the component and its members. As such, the descriptor
property of a component must always be defined directly on the component class itself.
The descriptor
property of a component references an object literal that contains one or more name/value pairs, where each name/value pair describes a specific group of members. The name part of the name/value pair that describes the properties of a component contains the word properties
, and the value part is an array of object literals where each object literal describes a particular property. In the case of the Label
control, this array contains two object literals, where the first object literal describes the htmlEncode
property and the second object literal describes the text
property (see Listing 6). Each object literal contains two name/value pairs. The name part of the first name/value pair is the word name
, and the value part is the string that contains the name of the property being described. The name part of the second name/value pair is the word type,
and the value part references the constructor of the type of the property being described.
Listing 6: The descriptor Property of the Label Control
Sys.Preview.UI.Label.descriptor = { properties: [ { name: 'htmlEncode', type: Boolean }, { name: 'text', type: String } ] }
Using Label Client Control
Listing 7 presents a page that uses the Label
client control.
Listing 7: A Page that Uses the Label Client Control
<%@ Page Language="C#" %> <!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>Untitled Page</title> <script type="text/javascript" language="javascript"> var label; function clickcb(domEvent) { var chkbx = $get("chkbx"); label.set_htmlEncode($get("chkbx").checked); var txtbx = $get("txtbx"); label.set_text(txtbx.value); } function pageLoad() { var btn = $get("btn"); $addHandler(btn, "click", clickcb); label = $create(Sys.Preview.UI.Label, null, null, null, $get("myspan")); } </script> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server"> <Scripts> <asp:ScriptReference Assembly="Microsoft.Web.Preview" Name="PreviewScript.js" /> </Scripts> </asp:ScriptManager> <input type="checkbox" id="chkbx"/> <label for="chkbx">Enable HTML encoding</label> <br /><br /> Enter text: <input type="text" id="txtbx" /> <button id="btn" type="button">Submit</button><br /><br /> <span id="myspan"></span> <div> </div> </form> </body> </html>
Figure 1 shows what you'll see in your browser when you access this page:
- A check box that allows you to toggle HTML encoding on or off
- A text box where you can enter text
- A Submit button
- A
<span>
HTML element

Figure 1
When you enter a text into the text box and click the Submit button, the callback for the button retrieves the text and displays it inside the <span>
HTML element. Figure 2 presents a different scenario from what's shown in Figure 1. The text "<b>ASP.NET AJAX </b>" is entered in both cases, containing the opening and closing tags of the <b>
HTML element. In Figure 1, however, the HTML encoding is off. In this case, the opening and closing tags of the <b>
HTML element are not HTML-encoded and consequently the <span>
HTML element shows the text in bold. In Figure 2, on the other hand, the HTML encoding is on. In this case, the opening and closing tags of the <b>
element are HTML encoded and consequently the <span>
element displays these tags as if they were normal non-HTML characters.

Figure 2
Note that the page shown in Listing 7 contains the following reference:
<asp:ScriptReference Assembly="Microsoft.Web.Preview" Path="PrevewScript.js" />
This script references a JavaScript file named PreviewScripts.js
that contains the definition of the Label
client control. This JavaScript file is embedded in the Microsoft.Web.Preview.dll
assembly. You need to add this assembly to the bin
directory of your application. When you install the Microsoft ASP.NET Futures, it automatically adds the necessary template to the Visual Studio. Therefore, if you use this template when you're creating a new Web site, the Microsoft.Web.Preview.dll
assembly will be automatically added to the bin
directory of your Web site.
As Listing 7 shows, pageLoad
calls the addHandler
static method on the DomEvent
class to register the clickcb
JavaScript function as the event handler for the click
event of the Submit button:
var btn = $get("btn"); $addHandler(btn, "click", clickcb);
Then pageLoad
instantiates an instance of the Label
client control to represent the <span>
HTML element:
label = $create(Sys.Preview.UI.Label, null, null, null, $get("myspan"));
Now let's walk through the code for the clickcb
JavaScript function. This function first uses the $get
global JavaScript function to return a reference to the check box element:
var chkbx = $get("chkbx");
It then passes the check box status into the set_htmlEncode
method of the Label
client control:
label.set_htmlEncode($get("chkbx").checked);
Finally, it calls the set_text
method on the Label
client control that represents the <span>
element to display the value entered into the text box:
var txtbx = $get("txtbx"); label.set_text(txtbx.value);
Image Client Control
The ASP.NET Image
server control is the ASP.NET representation of an image
DOM element. As such, it exposes the width
, height
, src
, and alt
properties of this DOM element as the Width
, Height
, ImageURL
, and AlternateText
properties on the Image
server control itself. This allows you to treat these DOM properties as properties on the Image
server-control.NET object. The ASP.NET AJAX Image
client control plays the same role in the ASP.NET AJAX client-side framework.
It is the ASP.NET AJAX representation of an image DOM element. As such, it exposes the DOM width
, height
, src
, and alt
properties of this DOM element as the width
, height
, imageURL
, and alterateText
properties on the Image
client control itself. This allows you to treat these DOM properties as properties on an ASP.NET AJAX Image
client control object. The following sections cover the implementation of the Image
client control members.
Constructor
As Listing 8 shows, the constructor of the Image
client control takes a single argument, which references the <img>
HTML element the Image
client control will represent. This constructor simply calls the initializeBase
method to invoke the constructor of its Control
base class, passing in the reference to the <img>
element. The registerClass
method is then called to register the Image
class as the subclass of the Control
base class.
Listing 8: The Constructor of the Image Client Control
Sys.Preview.UI.Image = function Sys$Preview$UI$Image(associatedElement) { Sys.Preview.UI.Image.initializeBase(this, [associatedElement]); } Sys.Preview.UI.Image.registerClass('Sys.Preview.UI.Image', Sys.UI.Control);
prototype
Listing 9 presents the implementation of the prototype
property of the Image
client control. In this implementation, an object literal describing all the instance methods of the control has been assigned to the prototype
property. As discussed in the previous chapter, an instance method of a class is a method that is directly defined on the prototype
property of the class, as opposed to the class itself. An instance method must always be invoked on an instance of a class, not the class itself.
Listing 9: The prototype Property of the Image Client Control
Sys.Preview.UI.Image.prototype = { get_alternateText: Sys$Preview$UI$Image$get_alternateText, set_alternateText: Sys$Preview$UI$Image$set_alternateText, get_height: Sys$Preview$UI$Image$get_height, set_height: Sys$Preview$UI$Image$set_height, get_imageURL: Sys$Preview$UI$Image$get_imageURL, set_imageURL: Sys$Preview$UI$Image$set_imageURL, get_width: Sys$Preview$UI$Image$get_width, set_width: Sys$Preview$UI$Image$set_width }
As you can see in this listing, the Image
client control exposes four pairs of instance methods. Each pair allows you to set and get the value of a particular property of the Image
class. For example, the set_height
and get_height
instance methods allow you to set and get the value of the height
property of the Image
client control.
The four properties that the Image
client control exposes — width,
height,
imageURL,
and alternateText
— are given the same names as the corresponding properties of its Image
server control counterpart to make client-side programming feel more like server-side ASP.NET programming.
image URL
The Image
client control exposes two methods named get_imageURL
and set_imageURL
that allow you to get and set the value of the src
property of the underling DOM element, as shown in Listing 10. As you can see from this code listing, both methods first call the get_element
method to return a reference to the <img>
element that the Image
client control represents. The Image
client control inherits this method from its Control
base class.
Listing 10: The set_imageURL and get_imageURL Methods of the Image Client Control
function Sys$Preview$UI$Image$get_imageURL() { return this.get_element().src; } function Sys$Preview$UI$Image$set_imageURL(value) { this.get_element().src = value; }
width
The Image
client control exposes two methods named get_width
and set_width
that allow you to get and set the value of the width
property of the image DOM element that the control represents. As you can see in Listing 11, these methods are just wrappers around the width
property of the DOM element, which means you can treat this the same way as a property on an ASP.NET AJAX object.
Listing 11: The set_width and get_width Methods of the Image Client Control
function Sys$Preview$UI$Image$get_width() { return this.get_element().width; } function Sys$Preview$UI$Image$set_width(value) { this.get_element().width = value; }
height
As you can see in Listing 12, the set_height
and get_height
methods act as wrappers around the height
property of the underlying image DOM element. This enables you to treat this as a property on an ASP.NET AJAX object, which is the Image
client control in this case.
Listing 12: The set_height and get_height Methods of the Image Client Control
function Sys$Preview$UI$Image$get_height() { return this.get_element().height; } function Sys$Preview$UI$Image$set_height(value) { this.get_element().height = value; }
alternate Text
The get_alternateText
and set_alternateText
methods allow you to get and set the value of the alt
property of the image DOM element using the ASP.NET AJAX client-side framework in the same way as you would to get and set the value of this property using the ASP.NET Framework (see Listing 13).
Listing 13: The set_alternateText and get_alternateText Methods of the Image Client Control
function Sys$Preview$UI$Image$get_alternateText() { return this.get_element().alt; } function Sys$Preview$UI$Image$set_alternateText(value) { this.get_element().alt = value; }
Using the Image Client Control
Listing 14 presents a page that uses the Image
client control. Previously, we implemented a similar page that showed how to use the Label
client control where the page used the following script reference to reference the PreviewScript.js
JavaScript file embedded in the Microsoft.Web.PreviewScript.dll
assembly:
<asp:ScriptReference Assembly="Microsoft.Web.Preview" Name="PreviewScript.js" />
As you can see, Listing 14 uses the same script reference because the same JavaScript file also contains the definition of the Image
client control.
Listing 14: A Page that uses the Image client control
<%@ Page Language="C#" %> <!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>Untitled Page</title> <script type="text/javascript" language="javascript"> function pageLoad() { var type = Sys.Preview.UI.Image; var properties = { imageURL: "wroxProgrammerSmall.jpg", alternateText : "Wrox Programmer's Reference Series", width: 155, height: 58 }; var events = null; var references = null; var element = $get("myImage"); $create(type, properties, events, references, element); } </script> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server"> <Scripts> <asp:ScriptReference Assembly="Microsoft.Web.Preview" Name="PreviewScript.js" /> </Scripts> </asp:ScriptManager> <img id="myImage" /> </form> </body> </html>
The pageLoad
method uses the $create
shortcut method (the shortcut for the create
static method of the Component
base class) to instantiate and initialize an Image
client control and to add the control to the _components
collection of the Application
object that represents the current ASP.NET AJAX application. pageLoad
passes the following parameters into the create
method:
type
: This parameter references the constructor of the component being created, which is theSys.Preview.UI.Image
constructor in this case.properties
: This parameter references an object (normally an object literal) that contains the names and values of the properties of the component being created that you want to initialize. Thecreate
method internally assigns these values to the properties with the specified names. In this case, the object literal contains four name/value pairs where the name and value parts of each pair respectively contain the name and value of a particular property of theImage
client control being created:
var properties = { imageURL: "wroxProgrammerSmall.jpg", alternateText : "Wrox Programmer's Reference Series", width: 155, height: 58 };
events
: This parameter references an object (normally an object literal) that specifies the event handlers that you want to register for events with the specified names. In this case, theevents
object isnull
so any event handlers will be registered.references
: This parameter references an object (normally an object literal) that specifies the values of the properties of the component being created that reference other components in the_components
collection of the currentApplication
object. In this case, this object isnull
because theImage
client control does not expose any properties that reference other components of the application.element
: This parameter references the DOM element on the current page that the newly createdImage
client control will represent. In this case, this parameter references the<img>
HTML element withid
HTML attribute value of" myimage"
:
var element = $get("myImage");
The pageLoad
method then invokes the create
method, passing in the five parameters to create the Image
client control:
$create(type, properties, events, references, element);
This article is excerpted from Chapter 8, "Developing Client Controls," of the book, ASP.NET AJAX Programmer's Reference (Wrox, 2007, ISBN: 978-0-470-10998-4,) by Dr. Shahram Khosravi. Shahram is a senior software engineer, consultant, author, and instructor specializing in ASP.NET, Web services, Windows Communication Foundation (WCF), ASP.NET AJAX, Windows Workflow Foundation (WF), IIS7 and ASP.NET Integrated Programming, .NET, Web Services, XML technologies, ADO.NET, and C#. He has more than 10 years of experience in object-oriented analysis, design, and programming. Shahram has written articles on the .NET Framework, ADO.NET, ASP.NET, and XML technologies for industry leading magazines such as Dr. Dobb's Journal, asp.netPRO magazine, and Microsoft MSDN Online. His other recent articles on Wrox.com are Developing Ajax-Enabled Controls and Components: Periodic Refresh Pattern and ASP.NET 2.0 WebPartChrome, both adapted from his first book, Professional ASP.NET 2.0 Server Control and Component Development (Wrox, 2006, ISBN: 0-471-79350-7). Shahram's next book, Professional IIS 7 and ASP.NET Integrated Programming, is also being published in 2007 by Wrox (ISBN: 978-0-470-15253-9).