In the first part of this series, we started with an example of a
simple web page that displays a Virtual Earth map on screen. The purpose of the code was to highlight some bad habits in writing markup and
what we are going to do starting from part two of this series.
Ajax-enabled Server Controls
One of the strength of the ASP.NET programming model is the ability to encapsulate the markup of a portion of the page and render it
dynamically. The rendering logic is located inside an object called a Server Control. The responsibility of this object is simple: it
determines which HTML will be written to the response stream, based on decisions made at runtime. This means that the generated markup can
vary based on user preferences, environment configuration, and business logic. The dynamic generation of the HTML of a web page is the main
philosophy behind server technologies like ASP.NET.
As a consequence, our ASP.NET AJAX page will contain a Panel control, which is responsible for rendering the
div element that
hosts the Virtual Earth map:
So far, everything is straightforward. In order to host a Virtual Earth map inside the div element, we need a Server Control
that performs two tasks:
- It renders a
script tag that loads the Virtual Earth API based on a default URL or one supplied by the
The code in listing 1 shows this Server Control declared in the ASP.NET AJAX page.
Listing 2: The VirtualEarthExtender control is an Ajax-enabled server control
The Server Control in the previous listing is not a typical ASP.NET control. In fact, it's a new kind of control - provided by
ASP.NET AJAX - called an Extender.
One reason for creating an Extender is that it lets you inject a
script tag programmatically by instantiating an object of
type ScriptReference. However, this can be done with classic ASP.NET controls, simply by invoking one of the methods of the
ClientScriptManager object, which is accessible through the
Page.ClientScript property. Actually, we are already gaining
something because we are encapsulating this logic inside a dedicated object, instead of interacting directly with the ClientScriptManager
to a HTML element in the page. In terms of ASP.NET markup, this means creating an Extender and associating it with another Server Control -
the "extended" control. Take a look at listing 1. Notice how we are associating the VirtualEarthExtender to the Panel through the
object is initially configured.
Based on the previous discussion, this is what you are going to do in the following paragraphs:
will create a client Control that encapsulates an instance of a Virtual Earth map.
Why create a wrapper over a VEMap object? There are multiple reasons. One is that the Microsoft Ajax Library enables you to do
component-based development on the client side. However, what interests us now is the possibility to use a client Control to manage the
Mashup.VirtualEarth client Control.
Listing 3: Mashup.VirtualEarth Control
The first line tells the Microsoft Ajax Library to create a namespace called
Mashup. Under this namespace, the
VirtualEarth control is declared as a function and then registered as a Control. This happens in the last line - the first after
the function body - through the call to the
AJAX client class and makes it inherit from
Sys.UI.Control, which is the base class for client Controls.
constructs as "object-oriented patterns".
Sys.UI.Control class provides two interesting methods called
These are the best places to perform the initial setup and the final cleanup of an instance. An example is attaching event handlers in the
initialize method and then detaching the same handlers in the
dispose method. As a consequence, this lets you
abandon the bad habit of hooking-up event handlers in the HTML. Furthermore, it enables you to detach handlers before the instance is
destroyed, thus avoiding potential memory leaks.
Finally, look at how the
Mashup.VirtualEarth function is declared. It accepts an argument called
element and passes
the same argument to the base class by calling the
initializeBase method. Every client Control is associated with one and only
one HTML element. In this example, the associated element will act as the container for the Virtual Earth map, since it's being passed to the
VEMap constructor inside the
Now that you've got a client Control, you need to wire it to a server Control - an Extender. This will enable you to instantiate and
The VirtualEarth Extender
Now you are going to create a VirtualEarth Extender that lets you instantiate and configure an instance of the
Mashup.VirtualEarth client Control. To create an Extender, you have to declare a class that inherits from the base
ExtenderControl class, as shown in the following listing.
Listing 4: Declaring an Extender
Just before the class declaration, there's a
TargetControlType attribute that specifies which server Controls can
be extended by our VirtualEarth Extender. In this case, you are restricting the extended Control to be a Panel, since it will render the div
element that will host the Virtual Earth map.
The next thing to do is declare some properties that allow setting the values of the counterpart properties of the client Control. The
following listing shows how it's done.
Listing 5: Mapping server properties to client properties
InitialLongitude properties let you specify the coordinates of the initial
location at which the map is centered. When the
Mashup.VirtualEarth instance is created on the client side, these values are
mapped to the
intialLongitude properties. The same thing happens for the
from the server side.
Finally, we need to write the code that creates an instance of the client Control and injects the references to the script files that
GetScriptControls. This is demonstrated in the following listing.
Listing 6: Working with Script Descriptors and Script References
GetScriptReferences method returns a collection of
ScriptReference objects. Each object specifies
script tag rendered in the page by the ScriptManager
RegisterScriptDescriptors method returns a collection of
ScriptDescriptor objects. Script Descriptors are
case, we are using a
ScriptControlDescriptor because we are going to instantiate a client Control.
Behind the Scenes
Now that the Extender is ready, let's browse the ASP.NET page and take a look at the source code. The first thing to notice is that the
VirtualEarth Extender injected two
script tags, just after those that reference the Microsoft Ajax Library files:
script tag references the Virtual Earth API, using the default URL or the one specified in the
ApiUrl property of the Extender. The second
script tag references the Mashup.VirtualEarth client Control. Both
these scripts were referenced in the
GetScriptReferences method of the Extender.
Sys.Application is a global object created by the Microsoft Ajax Library at runtime. This object accomplishes
some interesting tasks, such as hosting the client components instantiated on the client side. By calling the
you can participate in the Init stage of the client side page lifecycle. There, you have the opportunity to instantiate and configure the
Mashup.VirtualEarth client Control. You can do that by calling the
$create method and passing the configuration parameters, as
shown in the previous code snippet. Not only does
$create offer a convenient syntax to instantiate client Controls; it also
allows Extenders to leverage the same syntax in order to automatically create instances of client components at runtime. As you can see,
In the next part of this series, we will expand our Virtual Earth Control and explore other kinds of interactions between the server side
and the client side of an ASP.NET AJAX Web Application.
In the second part of this introduction to ASP.NET AJAX, we introduced client Controls and Extenders. Thanks to the Microsoft Ajax
initialized, set up and disposed in a standard way.
By creating an Extender, we can wire a client Control to a server Control. Then, we can configure the client Control on the server side
code that instantiates a client component.