Introduction
Microsoft ASP.NET AJAX enables you to write rich, interactive applications in JavaScript that target the browser. The Microsoft AJAX Library adds a type system and extensions to JavaScript objects in order to provide namespaces, inheritance, interfaces, enumerations, reflection, and helpers for strings and arrays. These additions provide functionality similar to the .NET Framework. They enable you to write ASP.NET AJAX applications in a structured way that improves maintainability, makes it easier to add features, and makes it easier to layer functionality.
In this section you will learn how to use the following JavaScript Microsoft AJAX Library features:
-
Classes
-
Namespaces
-
Inheritance
-
Interfaces
-
Enumerations
-
Reflection
Classes, Members, and Namespaces
Classes are reference types. All classes in JavaScript derive from object. (Similarly, in the .NET Framework class library, all classes derive from Object.) Classes in ASP.NET AJAX enable you to create objects and components that derive from base classes in the Microsoft AJAX Library by using an object-oriented programming model.
Classes can have four kinds of members: fields, properties, methods, and events. Fields and properties are name/value pairs that describe characteristics of an instance of a class. Fields are composed of primitive types and are accessed directly, as in the following example:
myClassInstance.name="Fred"
With properties, the value can be any primitive or reference type and is accessed by get and set accessor methods. In ASP.NET AJAX, the get and set accessors are separate functions, which by convention use the prefix "get_" or "set_" in the function name. For example, to get or set a value for a property such as cancel, you call the get_cancel or set_cancel methods.
A method is a function that performs an action instead of just returning a property value. Both methods and properties are illustrated in the examples in this topic.
Events are programmatic notifications that particular actions have occurred. When an event is raised, it can call one or more functions, referred to as handlers, to perform tasks that were waiting for that event. For more information about events in ASP.NET AJAX, see ASP.NET AJAX Client Life-Cycle Events.
A namespace is a logical grouping of related classes (types). Namespaces enable you to group common functionality. The following example demonstrates how to add a Person class to the Demo namespace using the Type.registerNamespace and .registerClass methods.
To enable ASP.NET AJAX functionality for an ASP.NET Web page, you must add an <asp:ScriptManager> control to the page. When the page is rendered, the appropriate script references to ASP.NET AJAX libraries are generated automatically. The following example shows a page with an <asp:ScriptManager> control.
cs
<asp:ScriptManager runat="server" ID="scriptManager" />
The following example shows how to register the namespace, create the class, and then register the class.
cs
Type.registerNamespace("Demo");Demo.Person = function(firstName, lastName, emailAddress) { this._firstName = firstName; this._lastName = lastName; this._emailAddress = emailAddress;}Demo.Person.prototype = { getFirstName: function() { return this._firstName; }, getLastName: function() { return this._lastName; }, getName: function() { return this._firstName + ' ' + this._lastName; }, dispose: function() { alert('bye ' + this.getName()); }}Demo.Person.registerClass('Demo.Person', null, Sys.IDisposable);// Notify ScriptManager that this is the end of the script.if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
To see a Web page that uses the preceding script file, click the Run It button.
Access Modifiers
Most object-oriented programming languages include the concept of access modifiers, which allow you to specify under what contexts a class or member is available, such as to outside programs, internal classes within the same namespace, or only within a specific code block. There are no access modifiers in JavaScript, however ASP.NET AJAX follows the convention that members with names that start with the underscore character ("_") are considered private and not accessed outside the class they are a part of.
Inheritance
Inheritance is the ability of one class to derive from another class. A derived class automatically inherits all the fields, properties, methods and events of the base class. A derived class also adds new members or overrides existing members of the base class to change their behavior.
The following example contains two classes defined in script: Person and Employee, where Employee derives from Person. Both classes illustrate the use of private fields, and both have public properties and methods. In addition, Employee overrides the toString implementation of the Person class, and uses the base class functionality.
cs
Type.registerNamespace("Demo");Demo.Person = function(firstName, lastName, emailAddress) { this._firstName = firstName; this._lastName = lastName; this._emailAddress = emailAddress;}Demo.Person.prototype = { getFirstName: function() { return this._firstName; }, getLastName: function() { return this._lastName; }, getEmailAddress: function() { return this._emailAddress; }, setEmailAddress: function(emailAddress) { this._emailAddress = emailAddress; }, getName: function() { return this._firstName + ' ' + this._lastName; }, dispose: function() { alert('bye ' + this.getName()); }, sendMail: function() { var emailAddress = this.getEmailAddress(); if (emailAddress.indexOf('@') < 0) { emailAddress = emailAddress + '@example.com'; } alert('Sending mail to ' + emailAddress + ' ...'); }, toString: function() { return this.getName() + ' (' + this.getEmailAddress() + ')'; }}Demo.Person.registerClass('Demo.Person', null, Sys.IDisposable);Demo.Employee = function(firstName, lastName, emailAddress, team, title) { Demo.Employee.initializeBase(this, [firstName, lastName, emailAddress]); this._team = team; this._title = title;}Demo.Employee.prototype = { getTeam: function() { return this._team; }, setTeam: function(team) { this._team = team; }, getTitle: function() { return this._title; }, setTitle: function(title) { this._title = title; }, toString: function() { return Demo.Employee.callBaseMethod(this, 'toString') + '/r/n' + this.getTitle() + '/r/n' + this.getTeam(); }}Demo.Employee.registerClass('Demo.Employee', Demo.Person);
To see a Web page that uses the preceding script file, click the Run It button.
Interfaces
An interface is a logical structure that defines the input and output requirements of classes that implement it. This enables a function to interact with classes that implement the same interface regardless of what other functionality the class implements.
The following example defines a Tree base class and an IFruitTree interface. Apple and Banana, two derived classes, implement the IFruitTree interface, but the Pine class does not.
cs
Type.registerNamespace("Demo.Trees");Demo.Trees.IFruitTree = function() {}Demo.Trees.IFruitTree.Prototype = { bearFruit: function(){}}Demo.Trees.IFruitTree.registerInterface('Demo.Trees.IFruitTree');Demo.Trees.Tree = function(name) { this._name = name;}Demo.Trees.Tree.prototype = { returnName: function() { return this._name; }, toStringCustom: function() { return this.returnName(); }, makeLeaves: function() {}}Demo.Trees.Tree.registerClass('Demo.Trees.Tree');Demo.Trees.FruitTree = function(name, description) { Demo.Trees.FruitTree.initializeBase(this, [name]); this._description = description;}Demo.Trees.FruitTree.prototype.bearFruit = function() { return this._description;}Demo.Trees.FruitTree.registerClass('Demo.Trees.FruitTree', Demo.Trees.Tree, Demo.Trees.IFruitTree);Demo.Trees.Apple = function() { Demo.Trees.Apple.initializeBase(this, ['Apple', 'red and crunchy']);}Demo.Trees.Apple.prototype = { makeLeaves: function() { alert('Medium-sized and desiduous'); }, toStringCustom: function() { return 'FruitTree ' + Demo.Trees.Apple.callBaseMethod(this, 'toStringCustom'); }}Demo.Trees.Apple.registerClass('Demo.Trees.Apple', Demo.Trees.FruitTree);Demo.Trees.GrannySmith = function() { Demo.Trees.GrannySmith.initializeBase(this); // You must set the _description feild after initializeBase // or you will get the base value. this._description = 'green and sour';}Demo.Trees.GrannySmith.prototype.toStringCustom = function() { return Demo.Trees.GrannySmith.callBaseMethod(this, 'toStringCustom') + ' ... its GrannySmith!';}Demo.Trees.GrannySmith.registerClass('Demo.Trees.GrannySmith', Demo.Trees.Apple);Demo.Trees.Banana = function(description) { Demo.Trees.Banana.initializeBase(this, ['Banana', 'yellow and squishy']);}Demo.Trees.Banana.prototype.makeLeaves = function() { alert('Big and green');}Demo.Trees.Banana.registerClass('Demo.Trees.Banana', Demo.Trees.FruitTree);Demo.Trees.Pine = function() { Demo.Trees.Pine.initializeBase(this, ['Pine']);}Demo.Trees.Pine.prototype.makeLeaves = function() { alert('Needles in clusters');}Demo.Trees.Pine.registerClass('Demo.Trees.Pine', Demo.Trees.Tree);
To see a Web page that uses the preceding script file, click the Run It button.
Enumerations
An enumeration is a class that contains a set of named integer constants. You access the values like properties, as in the following example:
myObject.color = myColorEnum.red
Enumerations provide an easily readable alternative to integer representations. For more information about enumerations in ASP.NET AJAX, see registerEnum Method.
The following example defines an enumeration of named colors that represent hexadecimal values.
cs
Type.registerNamespace("Demo");// Define an enumeration type and register it.Demo.Color = function(){};Demo.Color.prototype = { Red: 0xFF0000, Blue: 0x0000FF, Green: 0x00FF00, White: 0xFFFFFF }Demo.Color.registerClass("Demo.Color");
To see a Web page that uses the preceding script file, click the Run It button.
Reflection
Reflection is the ability to examine the structure and components of a program at run time. The APIs that implement reflection are extensions of the Type class. These methods enable you to collect information about an object, such as what it inherits from, whether it implements a particular interface, and whether it is an instance of a particular class.
The following example uses reflection APIs to test the GrannySmith class from the previous interface example.