ASP.NET AJAX Programmer’s Reference with ASP.NET 2.0 or ASP.NET 3.5 Dr Shahram Khosravi Wiley Publishing, Inc ffirs.indd v 8/25/07 2:41:01 AM ffirs.indd iv 8/25/07 2:41:00 AM ASP.NET AJAX Programmer’s Reference with ASP.NET 2.0 or ASP.NET 3.5 Acknowledgments xi Introduction xxix Chapter 1: AJAX Technologies Chapter 2: JavaScript Base Type Extensions 27 Chapter 3: Built-In and Custom Exception Types 53 Chapter 4: JavaScript Object-Oriented Programming and Type Reflection Extensions 77 Chapter 5: Event Programming Extensions 131 Chapter 6: DOM Extensions 161 Chapter 7: Component Development Infrastructure 219 Chapter 8: Developing Client Controls 281 Chapter 9: Event Bubbling and Button Client Control 323 Chapter 10: Type Description Extensions 349 Chapter 11: Data Classes 407 Chapter 12: Client-Server Communications 457 Chapter 13: Consuming Web Services Via Soap Messages 511 Chapter 14: Consuming Web Services Via JSON Messages 535 Chapter 15: Proxy Classes 597 Chapter 16: Behaviors 659 Chapter 17: Script and Extender Server Controls 707 Chapter 18: Web Services Bridges and Transformers 773 Chapter 19: UpdatePanel and ScriptManager 857 Chapter 20: Using UpdatePanel in User Controls and Custom Controls 911 Chapter 21: Page Life Cycle and Asynchronous Partial Page Rendering 965 Chapter 22: ASP.NET AJAX Client-Side PageRequestManager 1033 Continues ffirs.indd i 8/25/07 2:41:00 AM Chapter 23: Asynchronous Partial Page Rendering: Server Side Processing 1105 Chapter 24: Asynchronous Partial Page Rendering: Client-Side Processing 1179 Appendix A: XML Script 1275 Appendix B: Binding 1325 Appendix C: Actions 1341 Appendix D: Data Control 1357 Appendix E: Templated Controls 1381 Appendix F: ListView 1409 Index 1481 ffirs.indd ii 8/25/07 2:41:00 AM ASP.NET AJAX Programmer’s Reference with ASP NET 2.0 or ASP.NET 3.5 ffirs.indd iii 8/25/07 2:41:00 AM ffirs.indd iv 8/25/07 2:41:00 AM ASP.NET AJAX Programmer’s Reference with ASP.NET 2.0 or ASP.NET 3.5 Dr Shahram Khosravi Wiley Publishing, Inc ffirs.indd v 8/25/07 2:41:01 AM ASP.NET AJAX Programmer’s Reference with ASP.NET 2.0 or ASP.NET 3.5 Published by Wiley Publishing, Inc 10475 Crosspoint Boulevard Indianapolis, IN 46256 www.wiley.com Copyright © 2007 by Wiley Publishing, Inc., Indianapolis, Indiana Published simultaneously in Canada ISBN: 978-0-470-10998-4 Manufactured in the United States of America 10 No part of this publication may be reproduced, stored in a retrieval system or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, scanning or otherwise, except as permitted under Sections 107 or 108 of the 1976 United States Copyright Act, without either the prior written permission of the Publisher, or authorization through payment of the appropriate per-copy fee to the Copyright Clearance Center, 222 Rosewood Drive, Danvers, MA 01923, (978) 750-8400, fax (978) 646-8600 Requests to the Publisher for permission should be addressed to the Legal Department, Wiley Publishing, Inc., 10475 Crosspoint Blvd., Indianapolis, IN 46256, (317) 572-3447, fax (317) 572-4355, or online at http://www.wiley.com/go/permissions Limit of Liability/Disclaimer of Warranty: The publisher and the author make no representations or warranties with respect to the accuracy or completeness of the contents of this work and specifically disclaim all warranties, including without limitation warranties of fitness for a particular purpose No warranty may be created or extended by sales or promotional materials The advice and strategies contained herein may not be suitable for every situation This work is sold with the understanding that the publisher is not engaged in rendering legal, accounting, or other professional services If professional assistance is required, the services of a competent professional person should be sought Neither the publisher nor the author shall be liable for damages arising herefrom The fact that an organization or Website is referred to in this work as a citation and/or a potential source of further information does not mean that the author or the publisher endorses the information the organization or Website may provide or recommendations it may make Further, readers should be aware that Internet Websites listed in this work may have changed or disappeared between when this work was written and when it is read For general information on our other products and services or to obtain technical support, please contact our Customer Care Department within the U.S at (800) 762-2974, outside the U.S at (317) 572-3993 or fax (317) 572-4002 Library of Congress Cataloging-in-Publication Data: Khosravi, Shahram, 1963ASP.NET Ajax programmer’s reference / Shahram Khosravi p cm Includes index ISBN 978-0-470-10998-4 (paper/website) Active server pages Internet programming Web site development Ajax (Web site development technology) Microsoft NET I Title TK5105.8885.A26K538 2007 005.2'76 dc22 2007024239 Trademarks: Wiley, the Wiley logo, Wrox, the Wrox logo, Wrox Programmer to Programmer, and related trade dress are trademarks or registered trademarks of John Wiley & Sons, Inc and/or its affiliates, in the United States and other countries, and may not be used without written permission All other trademarks are the property of their respective owners Wiley Publishing, Inc., is not associated with any product or vendor mentioned in this book Wiley also publishes its books in a variety of electronic formats Some content that appears in print may not be available in electronic books ffirs.indd vi 8/25/07 2:41:01 AM About the Author Shahram Khosravi, Ph.D., is a senior software engineer, consultant, author, and instructor specializing in ASP.NET, Windows Communications Foundation (WCF), ASP.NET AJAX, Windows Workflow Foundation (WF), IIS7 and ASP.NET Integrated Programming, ADO.NET, Web services, NET, and XML technologies such as XSD, XSLT, XPath, SOAP, and WSDL He also has years of experience in object-oriented analysis, design, and programming, architectural and design patterns, service-oriented analysis, design, and programming, 3D computer graphics programming, user interface design, and usability Shahram is the author of the following four books: Professional ASP.NET 3.5 and NET 3.5 Programming (ASP.NET Internals plus ASP.NET AJAX, IIS 7.0, Enterprise Library Application Blocks, Windows Workflow Foundation, and Windows Communication Foundation), ASP.NET AJAX Programmer’s Reference with ASP NET 2.0 or ASP.NET 3.5, Professional IIS7 and ASP.NET Integrated Programming, and Professional ASP.NET Server Control and Component Development He has written articles on the ASP.NET, ADO.NET, NET, and XML technologies for the industry’s leading magazines, such as Dr Dobb’s Journal, asp.netPRO magazine, and Microsoft MSDN Online ffirs.indd vii 8/25/07 2:41:01 AM Chapter 4: JavaScript Object-Oriented Programming Listing 4-18 (continued) { var c = b.prototype[a]; if( ! this.prototype[a]) this.prototype[a] = c } delete this. basePrototypePending; } } This method first checks whether the _basePrototypePending field has been defined for the current type The registerClass method is the only place where this field is defined (see Listing 4-14) The registerClass method defines this field to tell the resolveInheritance method that it must execute the boldfaced code shown in Listing 4-18 Note that the resolveInheritance method deletes the _basePrototypePending field after it executes this boldfaced portion to ensure that this code is not executed more than once when the resolveInheritance method is called multiple times Now, let’s study the boldfaced code Note that the resolveInheritance is a recursive function because it is recursively called for each ancestor type of a specified type For example, when the resolveInheritance method of the Department.Manager class is called, the resolveInheritance method of the Department.Employee base class is automatically called as well As Listing 4-18 shows, when the resolveInheritance method of a class is called, the method first accesses the base class of the class: var b = this. baseType; It then iterates through the members (methods or properties) assigned to the prototype property of the base class and assigns each enumerated member (method or property) to the prototype property of the class on which the resolveInheritance method was called Therefore, the end result of calling the resolveInheritance method on a given type is that all the members assigned to the prototype properties of all its ancestor types are assigned to the prototype property of the type This is how the ASP.NET AJAX client-side framework manages to emulate the inheritance object-oriented feature in JavaScript to make client-side programming more like server-side NET programming call BaseMethod To understand the role of the callBaseMethod method, consider a similar situation in an OOP language such as C# A C# class exposes virtual methods to allow its subclasses to override the implementations of these methods This is how a subclass extends the functionality of its base class Most of the time, the subclass’s implementation of a virtual method calls its base class’s implementation in addition to providing its own implementation In other words, the subclass’s implementation complements the base class’s implementation 104 c04.indd 104 8/20/07 6:00:40 PM Chapter 4: JavaScript Object-Oriented Programming The callBaseMethod method in the ASP.NET AJAX client-side framework allows a subclass’s implementation of a method to call its base class’s implementation This is yet another step that the ASP.NET AJAX client-side framework takes to emulate the NET Framework To help you understand how this works in the ASP.NET AJAX client-side framework, I’ll walk through the example shown in Listing 4-19 Listing 4-19: An ASP.NET Page that Sets the Stage for using callBaseMethod Untitled Page Type.registerNamespace(“Department”); Department.IEmployee = function Department$IEmployee() { throw Error.notImplemented(); }; function Department$IEmployee$get_employeeID () { throw Error.notImplemented(); }; function Department$IEmployee$set_employeeID () { throw Error.notImplemented(); }; Department.IEmployee.prototype = { get_employeeID : Department$IEmployee$get_employeeID, set_employeeID: Department$IEmployee$set_employeeID } Department.IEmployee.registerInterface(“Department.IEmployee”); Department.Employee = function (firstName, lastName) { this._firstName = firstName; this._lastName = lastName; } Department.Employee.prototype = { get_firstName : function () {return this._firstName;}, set_firstName : function (value) {this._firstName = value;}, (continued) 105 c04.indd 105 8/20/07 6:00:41 PM Chapter 4: JavaScript Object-Oriented Programming Listing 4-19 (continued) get_lastName : function() {return this._lastName;}, set_lastName : function (value) {this._lastName = value;}, get_employeeID : function () {return this._employeeID;}, set_employeeID : function (value) {this._employeeID = value;}, getEmployeeInfo : function () { var info = ”First Name: “ + this.get_firstName() + “\n”; info += (“Last Name: “ + this.get_lastName() + “\n”); if (this._employeeID) info += (“Employee ID: “ + this._employeeID + “\n”); return info; } } Department.Employee.registerClass(“Department.Employee”, null, Department.IEmployee); Department.Manager = function (firstName, lastName, department) { Department.Manager.initializeBase(this,[firstName,lastName]); this._department = department; }; Department.Manager.prototype = { get_department : function () {return this._department;}, set_department : function (value) {this._department = value;} }; Department.Manager.registerClass(“Department.Manager”, Department.Employee); var mgr = new Department.Manager(“SomeFirstName”, “SomeLastName”, “SomeDepartment”); mgr.set_employeeID(324); alert (mgr.getEmployeeInfo()); As the first boldfaced portion of Listing 4-19 shows, a new function named getEmployeeInfo is added to the prototype property of the Department.Employee class This function simply displays the first name, last name, and employee ID of the current employee object Because the Department.Manager class derives from the Department.Employee class, it automatically inherits the getEmployeeInfo method from its base class That is why you can create an instance of the Department.Manager class and call this function on it as shown in the second boldfaced portion of Listing 4-19 If you run Listing 4-19, you get the pop-up message shown in Figure 4-2 Notice that this message displays the first name, last name, and employee ID, but it does not display the manager’s department This 106 c04.indd 106 8/20/07 6:00:41 PM Chapter 4: JavaScript Object-Oriented Programming is because the Department.Manager class inherits the Department.Employee class’s implementation of the getEmployeeInfo method, which does not contain the department information Figure 4-2 Listing 4-20 shows another example where the Department.Manager class overrides the getEmployeeInfo function to include the manager’s department name in the return information Listing 4-20: Overriding the getEmployeeInfo Function Untitled Page Type.registerNamespace(“Department”); Department.IEmployee = function Department$IEmployee() { throw Error.notImplemented(); }; function Department$IEmployee$get_employeeID () { throw Error.notImplemented(); }; function Department$IEmployee$set_employeeID () { throw Error.notImplemented(); }; (continued) 107 c04.indd 107 8/20/07 6:00:42 PM Chapter 4: JavaScript Object-Oriented Programming Listing 4-20 (continued) Department.IEmployee.prototype = { get_employeeID : Department$IEmployee$get_employeeID, set_employeeID: Department$IEmployee$set_employeeID } Department.IEmployee.registerInterface(“Department.IEmployee”); Department.Employee = function (firstName, lastName) { this._firstName = firstName; this._lastName = lastName; } Department.Employee.prototype = { get_firstName : function () {return this._firstName;}, set_firstName : function (value) {this._firstName = value;}, get_lastName : function() {return this._lastName;}, set_lastName : function (value) {this._lastName = value;}, get_employeeID : function () {return this._employeeID;}, set_employeeID : function (value) {this._employeeID = value;}, getEmployeeInfo : function () { var info = ”First Name: “ + this.get_firstName() + “\n”; info += (“Last Name: “ + this.get_lastName() + “\n”); if (this._employeeID) info += (“Employee ID: “ + this._employeeID + “\n”); return info; } } Department.Employee.registerClass(“Department.Employee”, null, Department.IEmployee); Department.Manager = function (firstName, lastName, department) { Department.Manager.initializeBase(this,[firstName,lastName]); this._department = department; }; Department.Manager.prototype = { get_department : function () {return this._department;}, set_department : function (value) {this._department = value;}, getEmployeeInfo : function() { var info = Department.Manager.callBaseMethod(this, “getEmployeeInfo”, null); info += (“Department: “ + this._department + “\n”); return info; } }; 108 c04.indd 108 8/20/07 6:00:42 PM Chapter 4: JavaScript Object-Oriented Programming Department.Manager.registerClass(“Department.Manager”, Department.Employee); var mgr = new Department.Manager(“SomeFirstName”, “SomeLastName”, “SomeDepartment”); mgr.set_employeeID(324); alert (mgr.getEmployeeInfo()); As the second boldfaced portion of Listing 4-20 shows, the Department.Manager class’s implementation of the getEmployeeInfo function calls the callBaseMethod function to invoke the Department.Employee class’s implementation of the getEmployeeInfo function As the first boldfaced portion of Listing 4-20 shows, the Department.Employee class’s implementation returns a string that contains the first name, last name, and employee ID information The callBaseMethod function under the hood invokes the getEmployeeInfo function and returns this string to its caller — that is the getEmployeeInfo function of the Department.Employee class, as shown here: var info = Department.Manager.callBaseMethod(this, “getEmployeeInfo”, null); Note that the callBaseMethod function takes three arguments The first argument references the instance of the Department.Manager class on which this function is called The second argument is the name of the base class’s method that the callBaseMethod is supposed to invoke The last argument, which is optional, is the parameters that the callBaseMethod function must pass into the base class’s method when it’s calling the method In this case, the base class method (getEmployeeInfo) does not take any parameters You don’t have to pass null as the third parameter if the base method does not take any parameters You can simply drop the last parameter The getEmployeeInfo function also appends the department information to the string that the callBaseMethod function returns: info += (“Department: “ + this._department + “\n”); As this example shows, thanks to the callBaseMethod function, the Department.Manager class’s implementation of the getEmployeeInfo function does not have to repeat its base class implementation If you run Listing 4-20, you get the pop-up message shown in Figure 4-3 Notice that the information displayed in this message contains the department information in addition to the first name, last name, and employee ID Figure 4-3 109 c04.indd 109 8/20/07 6:00:42 PM Chapter 4: JavaScript Object-Oriented Programming Listing 4-21 presents the internal implementation of the callBaseMethod function This function first calls a JavaScript function named getBaseMethod, which is discussed in the next section For now it suffices to say that this function returns a reference to the Function object that represents the base class’s implementation of the specified function Finally, the callBaseMethod function invokes the apply function on the referenced Function object to invoke the associated function Listing 4-21: The Internal Implementation of the callBaseMethod Function Type.prototype.callBaseMethod = function(a, d, b) { var c = this.getBaseMethod(a, d); if( ! b) return c.apply(a); else return c.apply(a, b); }; get BaseMethod The getBaseMethod function takes two arguments The first argument references the object on which this function was invoked The second argument contains a function name The main responsibility of the getBaseMethod function is to locate the Function object that represents the function with the specified name and return a reference to this Function object Take a look at Listing 4-22 to see what a reference to a Function object looks like Listing 4-22: A Page that uses the getBaseMethod Method Untitled Page Type.registerNamespace(“Department”); Department.IEmployee = function Department$IEmployee() { throw Error.notImplemented(); }; function Department$IEmployee$get_employeeID () { throw Error.notImplemented(); }; function Department$IEmployee$set_employeeID () { throw Error.notImplemented(); }; 110 c04.indd 110 8/20/07 6:00:43 PM Chapter 4: JavaScript Object-Oriented Programming Department.IEmployee.prototype = { get_employeeID : Department$IEmployee$get_employeeID, set_employeeID: Department$IEmployee$set_employeeID } Department.IEmployee.registerInterface(“Department.IEmployee”); Department.Employee = function (firstName, lastName) { this._firstName = firstName; this._lastName = lastName; } Department.Employee.prototype = { get_firstName : function () {return this._firstName;}, set_firstName : function (value) {this._firstName = value;}, get_lastName : function() {return this._lastName;}, set_lastName : function (value) {this._lastName = value;}, get_employeeID : function () {return this._employeeID;}, set_employeeID : function (value) {this._employeeID = value;}, getEmployeeInfo : function () { var info = ”First Name: “ + this.get_firstName() + “\n”; info += (“Last Name: “ + this.get_lastName() + “\n”); if (this._employeeID) info += (“Employee ID: “ + this._employeeID + “\n”); return info; } } Department.Employee.registerClass(“Department.Employee”, null, Department.IEmployee); Department.Manager = function (firstName, lastName, department) { Department.Manager.initializeBase(this,[firstName,lastName]); this._department = department; }; Department.Manager.prototype = { get_department : function () {return this._department;}, set_department : function (value) {this._department = value;}, getEmployeeInfo : function() { var info = Department.Manager.callBaseMethod(this, “getEmployeeInfo”, null); info += (“Department: “ + this._department + “\n”); return info; } }; (continued) 111 c04.indd 111 8/20/07 6:00:43 PM Chapter 4: JavaScript Object-Oriented Programming Listing 4-22 (continued) Department.Manager.registerClass(“Department.Manager”, Department.Employee); var mgr = new Department.Manager(“SomeFirstName”, “SomeLastName”, “SomeDepartment”); var ref1 = Department.Manager.getBaseMethod(mgr, “getEmployeeInfo”); alert (ref1); The second boldfaced portion of Listing 4-22 calls the getBaseMethod function on the Department Manager class, passing in a reference to the class itself and the string that contains the name of the getEmployeeInfo function If you run this code, you get the pop-up message shown in Figure 4-4 Compare the content of this message and the first bold portion of Listing 4-22 As you can see, the getBaseMethod function returns the getEmployeeInfo function of the base class — that is, the Department.Employee class Figure 4-4 Listing 4-23 presents the internal implementation of the function Listing 4-23: The getBaseMethod Method Type.prototype.getBaseMethod = function(d, c) { var b = this.getBaseType(); if(b) { var a = b.prototype[c]; return a instanceof Function ? a : null; } return null; }; 112 c04.indd 112 8/20/07 6:00:44 PM Chapter 4: JavaScript Object-Oriented Programming This function calls the getBaseType method to access the object that represents the base type of the current class: var b = this.getBaseType(); getBaseMethod then uses the name of the function as an index into the prototype collection property of the object that represents the base type to access and returns the Function object that represents the function with the specified name: var a = b.prototype[c]; return a instanceof Function ? a : null implements Interface The implementsInterface function takes an interface as its argument and returns a Boolean value that specifies whether the type on which the function is called implements the specified interface Here’s an example: Untitled Page function getEmployeeID(obj) { var objType = Object.getType(obj); alert(objType); var flag = objType.implementsInterface(Department.IEmployee); alert(flag); if (!flag) throw Error.argument( “Must implement the Department.IEmployee interface”); return obj.getemployeeID(); } Type.registerNamespace(“Department”); Department.IEmployee = function Department$IEmployee() { throw Error.notImplemented(); }; function Department$IEmployee$get_employeeID () { throw Error.notImplemented(); }; (continued) 113 c04.indd 113 8/20/07 6:00:44 PM Chapter 4: JavaScript Object-Oriented Programming function Department$IEmployee$set_employeeID () { throw Error.notImplemented(); }; Department.IEmployee.prototype = { get_employeeID : Department$IEmployee$get_employeeID, set_employeeID: Department$IEmployee$set_employeeID } Department.IEmployee.registerInterface(“Department.IEmployee”); Department.Employee = function (firstName, lastName) { this._firstName = firstName; this._lastName = lastName; } Department.Employee.prototype = { get_firstName : function () {return this._firstName;}, set_firstName : function (value) {this._firstName = value;}, get_lastName : function() {return this._lastName;}, set_lastName : function (value) {this._lastName = value;}, get_employeeID : function () {return this._employeeID;}, set_employeeID : function (value) {this._employeeID = value;}, getEmployeeInfo : function () { var info=”First Name: “ + this.get_firstName() + “\n”; info += (“Last Name: “ + this.get_lastName() + “\n”); if (this._employeeID) info += (“Employee ID: “ + this._employeeID + “\n”); return info; } } Department.Employee.registerClass(“Department.Employee”, null, Department.IEmployee); Department.Manager = function (firstName, lastName, department) { Department.Manager.initializeBase(this,[firstName, lastName]); this._department = department; }; Department.Manager.prototype = { get_department : function () {return this._department;}, set_department : function (value) {this._department = value;}, getEmployeeInfo : function() { var info = Department.Manager.callBaseMethod(this, “getEmployeeInfo”, null); info += (“Department: “ + this._department + “\n”); 114 c04.indd 114 8/20/07 6:00:44 PM Chapter 4: JavaScript Object-Oriented Programming return info; } }; Department.Manager.registerClass(“Department.Manager”, Department.Employee); var mgr = new Department.Manager(“SomeFirstName”, “SomeLastName”, “SomeDepartment”); mgr.set_employeeID(234); var employeeID = getEmployeeID(mgr); alert (employeeID); As the second boldfaced portion of this code listing shows, the Department.Employee class directly implements the Department.IEmployee interface As you’ll see shortly, even though the Department Manager class does not directly implement this interface, the call into the implementsInterface function returns true because this class derives from the Department.Employee class The third boldfaced portion of this code listing first instantiates an instance of the Department Manager class: var mgr = new Department.Manager(“SomeFirstName”, “SomeLastName”, “SomeDepartment”); It then calls a JavaScript function named getEmployeeID, passing in the Department.Manager object to return the employee ID of the object: var employeeID = getEmployeeID(mgr); Finally, it displays the employee ID: alert (employeeID); The first boldfaced portion of this code listing presents the implementation of the getEmployeeID JavaScript function This function takes an object as its argument and performs the following tasks: It calls the getType function of the JavaScript Object, passing in the object that was passed into it: var objType = Object.getType(obj); As previously discussed, the getType function returns an object that references the type of a specified object In this case, the Department.Manager object is passed into the getType function, which means that this function returns the Function object that represents the Department.Manager class It calls the alert function to display the return value of the getType function: alert(objType); 115 c04.indd 115 8/20/07 6:00:45 PM Chapter 4: JavaScript Object-Oriented Programming As Figure 4-5 shows, in this case the getType function returns the Function object that represents the constructor of the Department.Manager class Figure 4-5 It calls the implementsInterface function on the return value of the getType function, passing in the Department.IEmployee interface: var flag = objType.implementsInterface(Department.IEmployee); The implementsInterface function determines whether the type on which the function is called (and its ascendant types) implements the specified interface In this case, the Department.Manager type does not directly implement the Department.IEmployee interface However, its parent class, Department.Employee, does implement this interface That is why the implementsInterface function returns true It throws a Sys.ArgumentException exception if the specified type does not implement the specified interface: if (!flag) throw Error.argument(“Must implement the Department.IEmployee interface”); It calls the getemployeeID function on the specified object if the specified type does indeed implement the specified interface: return obj.getemployeeID(); In this case, the Department.Manager class inherits the getEmployeeID function from its base class, Department.Employee Listing 4-24 presents the internal implementation of the implementsInterface function 116 c04.indd 116 8/20/07 6:00:45 PM Chapter 4: JavaScript Object-Oriented Programming Listing 4-24: The Internal Implementation of implementsInterface Type.prototype.implementsInterface = function(d) { this.resolveInheritance(); var c = d.getName(), a = this. interfaceCache; if(a) { var e = a[c]; if(typeof e !== “undefined”) return e; } else a = this. interfaceCache = {}; var b = this; while(b) { var f = b. interfaces; if(f) if(Array.indexOf(f, d) !== - 1) return a[c] = true; b = b. baseType; } return a[c] = false; }; This function first calls the resolveInheritance function: this.resolveInheritance(); This is a recursive function It copies all members of the prototype collection properties of the current type’s ancestor types into the prototype collection property of the current type Therefore, after this call, the current type contains all members that it inherits from its ancestor types This is how the ASP.NET AJAX client-side framework emulates inheritance, as discussed previously This step is important because there are cases such as Department.Manager where the current type itself does not implement a given interface, but one of its ancestor types does The resolveInheritance method copies the interfacerelated members such as getEmployeeID to the prototype collection property of the current type The implementsInterface function then calls the getName function on the interface passed into it to access the fully qualified name of the interface: var c = d.getName(); The function then accesses an internal collection named _interfaceCache: var a = this. interfaceCache; As you’ll see shortly, this collection caches the fully qualified names of all interfaces that the current type and its ancestor types implement This cache is added to improve performance 117 c04.indd 117 8/20/07 6:00:46 PM Chapter 4: JavaScript Object-Oriented Programming If the cache contains an entry for the specified interface, the function retrieves the interface directly from the cache and returns it: if(a) { var e = a[c]; if(typeof e !== “undefined”) return e; } If the cache hasn’t been created yet, it instantiates the cache: else a = this. interfaceCache = {}; Finally, the function iterates through the current type and all its ancestor types to determine whether the _interfaces collection of any of these types contains an entry for the specified interface If so, it adds an entry for the interface to the cache and returns the interface: var b = this; while(b) { var f = b. interfaces; if(f) if(Array.indexOf(f, d) !== - 1) return a[c] = true; b = b. baseType } return a[c] = false Caching allows you to avoid going through this logic the next time inherits From The inheritsFrom function returns a Boolean value that specifies whether the type on which the inheritsFrom is called inherits from the type passed into it as its argument The following code presents an example where the inheritsFrom function is called on the Department.Manager type to determine whether this type inherits from the Department.Employee type: Untitled Page Type.registerNamespace(“Department”); 118 c04.indd 118 8/20/07 6:00:46 PM ... _scriptsLoadComplete 11 21 112 1 11 22 11 23 11 24 11 62 11 78 11 79 11 79 12 07 12 09 12 09 12 10 12 10 12 11 1 212 12 12 12 12 12 13 12 13 12 13 12 15 12 17 12 18 12 18 12 19 12 19 12 20 12 21 12 21 _pageLoaded 12 23 _endPostBack... 10 0 10 2 10 3 10 4 11 0 11 3 11 8 12 1 12 3 12 5 12 7 12 9 12 9 13 0 13 1 13 1 13 2 13 2 13 3 13 8 13 8 14 4 15 9 16 1 16 1 16 1 16 6 16 7 16 7 16 9 17 1 17 2 17 5 MouseButton Key Delegates 17 6 17 6 17 7 Namespace Mover 18 3 18 4... Method of PageRequestManager 10 46 10 50 10 50 10 52 10 55 10 71 10 71 1077 10 81 1090 10 92 10 99 11 01 110 4 11 05 11 05 11 09 11 11 111 1 11 12 Load Post Data 11 13 UpdatePanel 11 17 ScriptManager The LoadPostData