Creating AJAX Server Control
A new project for ASP.NET AJAX Server Control can be created from the New Project dialog box by choosing the ASP.NET AJAX Server Control template under Visual C# - Web project type. The same template is also available under Visual Basic – Web for VB.Net as the coding language.
Figure 1. New Project for ASP.NET AJAX Server Control

As shown in Figure 1 above, the two AJAX-based server control templates (ASP.NET AJAX Server Control and ASP.NET AJAX Server Control Extender) are available only with .NET Framework 3.5. These templates are not available if you choose an earlier version in the Framework version dropdown in the New Project dialog box.
The Generated Files
In addition to the usual files that get generated for Visual Studio projects (for example, .sln, AssemblyInfo.cs, etc.), you will see the following two files:
- ClientControl1.js
- ServerControl1.cs
Figure 2. AJAX Server Control project with js and cs files

As shown in Figure 2 above, the file ClientControl1.js contains JavaScript code that provides the AJAX functionality on the client (i.e. browser). And the code in ServerControl1.cs knows how to refer to the client code.
Now let’s look at the code in these two files.
JavaScript code in the AJAX Server Control
The code listing below shows the code from the JavaScript file ClientControl1.js.
Code Listing 1. The client-side code in AJAX Server Control
/// <reference name="MicrosoftAjax.js"/>
Type.registerNamespace("AjaxServerControl1");
AjaxServerControl1.ClientControl1 = function(element) {
AjaxServerControl1.ClientControl1.initializeBase(this, [element]);
}
AjaxServerControl1.ClientControl1.prototype = {
initialize: function() {
AjaxServerControl1.ClientControl1.callBaseMethod(this, initialize);
// Add custom initialization here
},
dispose: function() {
//Add custom dispose actions here
AjaxServerControl1.ClientControl1.callBaseMethod(this, dispose);
}
}
AjaxServerControl1.ClientControl1.registerClass(AjaxServerControl1.ClientControl1, Sys.UI.Control);
if (typeof(Sys) !== undefined) Sys.Application.notifyScriptLoaded();
This client-side code can be broadly categorized into the following areas:
- Associating with a namespace
- Defining the class for the control
- Registering the class
Now let’s look at the various pieces of this code.
Associating with a namespace
Code Listing 2. The Namespace for the AJAX Server Control
Type.registerNamespace("AjaxServerControl1");
The method registerNamespace() is not part of the basic JavaScript, but comes from the ASP.NET AJAX extensions. This method provides the namespace concept that is available in languages like C# to the code written in JavaScript. Here AjaxServerControl1 namespace is created and the client control class that would be generated below would be part of this namespace.
Defining the class for the control
Now creating the class and the associated methods that do the work on the client side.
Code Listing 3. The class for the AJAX Server Control
AjaxServerControl1.ClientControl1 = function(element) {
AjaxServerControl1.ClientControl1.initializeBase(this, [element]);
}
AjaxServerControl1.ClientControl1.prototype = {
initialize: function() {
AjaxServerControl1.ClientControl1.callBaseMethod(this, initialize);
// Add custom initialization here
},
dispose: function() {
//Add custom dispose actions here
AjaxServerControl1.ClientControl1.callBaseMethod(this, dispose);
}
}
As shown in the code above, the ‘class’ comes in two pieces:
- The declaration of the class (via function)
- The methods associated to that class (via prototype)
The starting line in the code above declares a function, which is assigned to ClientControl1. In the native JavaScript, there are no object-oriented programming concepts as you would see in C# or Java. However, the function and the prototype (in the lines below) can be made to behave roughly like a class in object-oriented programming languages.
The second section of the code above associates a couple of methods with the prototype for ClientControl1. By default, shells for two methods are generated: initialize() and dispose().
Registering the class
And, finally, the class that has just been created needs to be registered.
Code Listing 4. Registering AJAX Server Control Class
AjaxServerControl1.ClientControl1.registerClass(AjaxServerControl1.ClientControl1, Sys.UI.Control);
The registerClass() method above has two parameters. First one is the class to be registered – ClientControl1 and the second one is the base class. Here the base class is Sys.UI.Control.
Server code in the AJAX Server Control
The server-side code (in C#) is in the file ServerControl1.cs.
Code Listing 5. Server Code in the AJAX Server Control
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml.Linq;
namespace AjaxServerControl1
{
/// <summary>
/// Summary description for ServerControl1
/// </summary>
public class ServerControl1 : ScriptControl
{
public ServerControl1()
{
//
// TODO: Add constructor logic here
//
}
protected override IEnumerable<ScriptDescriptor>
GetScriptDescriptors()
{
ScriptControlDescriptor descriptor = new ScriptControlDescriptor("AjaxServerControl1.ClientControl1", this.ClientID);
yield return descriptor;
}
// Generate the script reference
protected override IEnumerable<ScriptReference>
GetScriptReferences()
{
yield return new ScriptReference("AjaxServerControl1.ClientControl1.js", this.GetType().Assembly.FullName);
}
}
}
There are three things of interest in the above code:
- The Base Class
- GetScriptDescriptors()
- GetScriptReference()
The Base Class
The base class for this control (on the server side) is ScriptControl.
Code Listing 6. The Base Class for AJAX Server Control
public class ServerControl1 : ScriptControl
The ScriptControl class is part of the System.Web.UI namespace, which is part of the ‘traditional’ .Net Framework that you are used to (unlike the Sys.UI.Control class above, which is a ‘class’ in the JavaScript code provided in the ASP.NET AJAX Extensions).
The ScriptControl class itself is derived from the WebControl class. You would use the WebControl class as the base class for custom controls (server controls) that have user interface. And, of course, the WebControl class is derived from the Control class, which is the ultimate base class for all the custom controls.
So, AJAX Server Control that is being created here has access to all the basic functionality available in the Control and WebControl classes. In addition, ScriptControl class has two important methods: GetScriptDescriptors() and GetScriptReferences().
GetScriptDescriptors()
The derived code overrides the GetScriptDescriptors() method.
Code Listing 7. GetScriptDescriptors()
protected override IEnumerable<ScriptDescriptor>
GetScriptDescriptors()
{
ScriptControlDescriptor descriptor = new ScriptControlDescriptor("AjaxServerControl1.ClientControl1", this.ClientID);
yield return descriptor;
}
This method returns a ScriptControlDescriptor. This class (ScriptControlDescriptor) is derived from ScriptComponentDescriptor, which is ultimately derived from ScriptDescriptor. The ScriptComponentDescriptor has methods like AddProperty() and AddEvent() to help with adding properties and event handlers.
GetScriptReferences()
Another method overridden is GetScriptReferences().
Code Listing 8. GetScriptReferences()
// Generate the script reference
protected override IEnumerable<ScriptReference>
GetScriptReferences()
{
yield return new ScriptReference("AjaxServerControl1.ClientControl1.js", this.GetType().Assembly.FullName);
}
The JavaScript code that provides the client-side functionality is written in .js files. The GetScriptReferences() method returns these JavaScript files (as a part of the ScriptReference object). These JavaScript files could be stand-alone, but in this case (since this is a control), the JavaScript files are embedded in the assembly itself (the dll that would be in the bin directory). That’s why the second parameter is name of the assembly (this.GetType().Assembly.FullName)