Using the Type System


JavaScript has a familiar syntax if you are used to C#, Java, or C++. But as you saw in Chapter 3, JavaScript does not have built-in support for most OOP (object-oriented programming) concepts. This is not a problem by itself, but as you switch back and forth between C# or VB.NET and JavaScript, you may find that you miss the familiar OOP constructs. There is no support for inheritance of types and no standard way of declaring interface definitions or enumerations. What’s a developer to do? In the past, it meant that you adopted your own conventions in writing JavaScript. This becomes problematic as more people with unique approaches are added to a project, because there can be inconsistencies that make maintenance and new development more difficult. ASP.NET AJAX proves the ability to leverage OOP constructs when writing JavaScript. You will see a lot of small code examples that demonstrate a set of recommended standard patterns and show how the Microsoft AJAX Library functions are used.

The AJAX Library brings classic OOP concepts to JavaScript. It adds namespace support for grouping functionality. It also provides helpful debugging facilities, a schema for providing type information, and a means for localizing string and image resources.

Part of the ASP.NET team’s motivation for creating the AJAX Library and these patterns for development was to make JavaScript coding more like the C# coding that developers are used to. The team has tried to find the right balance between leveraging the features of a dynamic language and adopting a rigid approach more suitable to development with a statically typed language.

Declaring Namespaces

In the .NET Framework, like functionality is grouped into namespaces. Graphics classes are under the System.Graphics namespace, while ASP.NET Framework classes are under the System.Web names-pace. The use of namespaces is central to providing an organized and structured way for finding and accessing functionality. Namespaces are nothing more than prefixes used in front of class and type names, but through the use of standard conventions they are used to organize sets of similar functionality and are then typically housed in a single DLL. Your application declares what assemblies are referenced at compiletime, and this establishes what namespaces are available for use during development and which assemblies are required at runtime. The AJAX Library also supports the concept of names-paces. It uses namespaces for its own objects and provides you with the ability to do the same.

The AJAX Library synthesizes namespaces by creating objects with those names. Class definitions can be organized logically in just the same way that you would organize them using C# or VB.NET. You can group functionality naturally into separate namespaces and use them as independent resources. If you create separate files for different namespaces, you can even load them conditionally the same way the Common Language Runtime loads just the assemblies it needs for an application and does so on demand. This achieves a benefit similar to what happens in .NET Framework applications where the overhead associated with using some functionality in a namespace is not incurred unless the feature is used. It is a pay-for-play model. An application doesn’t need to send the script associated with a names-pace if the functionality isn’t used in that page.

Listing 4-2 (from Namespaces.aspx) demonstrates the basics of namespace support. The Wrox.ASPA- JAX.Samples namespace is created via Type.registerNamespace. Notice that you do not have to first create the Wrox and Wrox.ASPAJAX namespaces in order to register the Samples namespace under them. You can specify the whole namespace, and the AJAX Library will automatically create any levels of the hierarchy that do not exist already.

Listing 4-2

image from book
  <!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>ASP.NET AJAX Namespaces</title> <script type="text/javascript"> function pageLoad(sender, args) {     Type.registerNamespace('Wrox.ASPAJAX.     alert(Type.isNamespace(Wrox.ASPAJAX)); //displays      alert(Type.isNamespace(Wrox.ASPAJAX.Samples.Album)); //displays      var namespaces = Type.getRootNamespaces();     for(var i = 0, length = namespaces.length; i < length; i++) {         alert(namespaces[i].getName()); //displays      } }  </script> </head> <body>     <form  runat="server">     <asp:ScriptManager runat="server"  />     <div>     </div>     </form> </body> </html> 
image from book

The call to Type.registerNamespace creates three different objects: Wrox, ASPAJAX, and Samples. The Wrox object contains the ASPAJAX object, which in turn contains the Samples object. The objects all carry some metadata so the type system can identify them as namespaces and use them to hold any other objects that are added to the namespace.

The Type.isNamespace function returns a Boolean. The code didn’t create an Album namespace, so for that check, it returns false. The set of global namespaces is retrieved by calling Type.getRootnamespaces. Looping through the returned array and calling getName on each reveals that, in addition to the new Wrox namespace, there is also a Sys namespace. It contains the AJAX Library functionality.

Although doing so is not technically required, I recommend using namespaces to organize your own code, even if just to avoid cluttering up the global namespace. Because JavaScript is an interpreter language, the operation of resolving names is expensive. Every time you call a function, the JavaScript engine has to figure out where the code lives. Resolving variables also involves searching the current scope and containing scopes until the reference is resolved. The more global objects you have, the more expensive it is for the script engine to access them. Namespace objects also allow navigating to classes in the hierarchy more readily than would happen in a flat global arrangement. Thus, namespaces offer a performance benefit as well as providing a programmer convenience for grouping functionality. Namespaces by themselves, however, are not much use until your create classes in them that will provide useful functionality.

Scope is not just important in resolving namespaces and variable namespaces. Listing 4-3 (from Scope.aspx) demonstrates scope in JavaScript. The code uses global variable x and passes it to a function called doSomething, where x is doubled. After the function returns, the value of x is the same as before the call. The change to x is scoped to the function. The call to the function is performed by passing a value, not a reference. The return value of the function is not assigned back to the global x variable.

Listing 4-3

image from book
  <!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>Trace Console</title>     <script type="text/javascript"> var x = 38; var y = 38; function doSomething(x) {     x = x + x;     y = y + y;     alert("x = " + x + " now and y = " + y);       return x; } function pageLoad(sender, args) {      alert("before calling doSomething x = " + x + " and y = " + y);      doSomething(x);      alert("x still equals " + x + " but y now equals " + y); }     </script> </head> <body>     <form  runat="server">         <div>     <asp:ScriptManager runat="server"  />     </div>     </form> </body> </html> 
image from book

Creating Classes

JavaScript functions are used to represent class objects in the type system. The AJAX Library follows the pattern of declaring a function as the class constructor. JavaScript allows you to modify the prototype of the function directly, which is how the AJAX Library creates class members. The class must then be registered so that it can participate in the semantics of the type system. Listing 4-4 (Class.aspx) creates the Album type in the Wrox.ASPAJAX.Samples namespace. The constructor takes two parameters and assigns them to local variables. The object prototype is modified to declare two property accessors.

Listing 4-4

image from book
  <!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>ASP.NET AJAX Class</title>     <script type="text/javascript"> function pageLoad(sender, args) {     Type.registerNamespace('Wrox.ASPAJAX.Samples.     Wrox.ASPAJAX.Samples.Album = function(title, artist) {         this._title = title;         this._artist = artist;     }     Wrox.ASPAJAX.Samples.Album.prototype = {         get_title: function () {             return this._title;         },         get_artist: function() {             return this._artist;         }     }     Wrox.ASPAJAX.Samples.Album.registerClass('Wrox.ASPAJAX.Samples.     var anAlbum = new Wrox.ASPAJAX.Samples.Album("Round Room", "Phish ");      alert(anAlbum.get_title()); }     </script> </head> <body>     <form  runat="server">         <div>     <asp:ScriptManager runat="server"  />     </div>     </form> </body> </html> 
image from book

Tip 

Notice that the local members are accessed with a prefix of this. The script engine can then scope the lookup to the type and avoid searching any containing scopes. If you do not use this to indicate that the reference is local to the type, you will end up creating objects in the global scope and see errors that can be confusing and time-consuming to track down.

The call to registerClass looks a little odd, as it is on the type being registered. The prototype of the base type in JavaScript has been modified to add type-system support. Once the type is registered, an instance of it can be created and its members called.

The registerClass function actually has three possible parameters: The first one is for the name of the type, the second is for the base type being extended, and the last is to specify any interfaces that the class implements. Instances of using these classes are provided in later examples in this chapter.

JavaScript treats parameters as optional. This can be convenient. Instead of needing to define a bunch of different methods with different names in order to accommodate different combinations of parameters, you can write just one that knows how to process all of the optional inputs. Because the language treats all parameters as optional, however, you need to explicitly check that the inputs are valid for what you are doing. The caller can invoke the function with whatever set of parameters it wants to pass.

Although JavaScript allows types to be dynamically modified, and ASP.NET AJAX uses this to add the type system functionality into existing objects, it is not the approach recommended for mainstream development. Instead of modifying a type directly, you can inherit from it and extend it in new members by overriding existing ones. In Listing 4-5 (Inheritance.aspx), the Album type is extended by the TributeAlbum class, and adds one more piece of information: the artist being honored.

Listing 4-5

image from book
 <!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>ASP.NET AJAX Class</title>     <script type="text/javascript"> function pageLoad(sender, args) {     Type.registerNamespace('Wrox.ASPAJAX.Samples.     Wrox.ASPAJAX.Samples.Album = function(title, artist) {         this._title = title;         this._artist = artist;     }     Wrox.ASPAJAX.Samples.Album.prototype = {         get_title: function () {             return this._title;         },         get_artist: function() {             return this._artist;         }     }     Wrox.ASPAJAX.Samples.Album.registerClass('Wrox.ASPAJAX.Samples.     Wrox.ASPAJAX.Samples.TributeAlbum = function(title, artist, tributeArtist) {         Wrox.ASPAJAX.Samples.TributeAlbum.initializeBase(this, [title, artist]);         this._tributeArtist = tributeArtist;     }     Wrox.ASPAJAX.Samples.TributeAlbum.prototype = {         get_tributeArtist: function() {             return this._tributeArtist;         },         set_tributeArtist: function(tributeArtist) {             this._tributeArtist = tributeArtist;         }     }      Wrox.ASPAJAX.Samples.TributeAlbum.registerClass(         'Wrox.ASPAJAX.Samples.TributeAlbum',          Wrox.ASPAJAX.Samples.Album);      var anotherAlbum = new Wrox.ASPAJAX.Samples. Groove", "Various Artists", "Phish");      alert(anotherAlbum.get_title ());       alert(anotherAlbum.get_tributeArtist()); }     </script> </head> <body>     <form  runat="server">         <div>     <asp:ScriptManager runat="server"  />     </div>     </form> </body> </html>
image from book

The constructor must explicitly call initializeBase and pass itself, using the this keyword, along with an array of the arguments to pass to the constructor of the base type. The AJAX Library allows you to employ object-oriented principles, but doing so requires that you follow some coding patterns like this. Without the call to initializeBase, when you try to call something on the base type, you will get an error. In Internet Explorer, the message reads: Object doesn't support this property or method. This is not the most helpful message! In Firefox, it fails silently, but if you have the JavaScript console open, an error message is displayed that more explicitly identifies the actual problem: anotherAlbum.get_title is not a function. Chapter 9 provides more details about debugging.

The call to initializeBase takes care of producing the final type with inheritance semantics in place. The base class constructor is called with the arguments provided.

The type system of the AJAX Library also provides some reflection functions that let you explore the relationship between objects. Listing 4-6 (from InheritsFrom.aspx) demonstrates calls to inheritsFrom and isInstanceOftype using the Album and TributeAlbum types. It is simply a copy of the Inheritance.aspx page with these lines added at the end of the pageLoad function. Again, you see that these methods are available automatically as part of using ASP.NET AJAX. The AJAX Library has modified the underlying JavaScript type so that any class you register can use this functionality.

Listing 4-6

image from book
  if(Wrox.ASPAJAX.Samples.TributeAlbum.isInstanceOfType(anAlbum) == false) {     alert("anAlbum is not a TributeAlbum"); } if (Wrox.ASPAJAX.Samples.TributeAlbum.isInstanceOfType(anotherAlbum) == true) {     alert("anotherAlbum is a TributeAlbum"); } if (Wrox.ASPAJAX.Samples.TributeAlbum.inheritsFrom(Wrox.ASPAJAX.Samples.Album) == true ) {     alert("TributeAlbum inherits from Album"); } if (Wrox.ASPAJAX.Samples.Album.inheritsFrom(Wrox.ASPAJAX.Samples.TributeAlbum) == true) {     alert("Album does not inherit from TributeAlbu7");  } 
image from book

At first glance, the type references in Listing 4-6 look long. JavaScript doesn’t have the equivalent of the using statement that makes namespaces available to code without being explicit. With a compiled language, the cost of the lookup can be paid when the binary is created and symbolic references are created. In an interpreted language like JavaScript, you can speed up the lookup by providing a shortcut for the long type name by providing aliases that reference the fully qualified name. When you create global object aliases, you defeat the purpose of the namespace containers. Each subsequent lookup can get a little more expensive for every item in the checked scope. The ideal time to create aliases is when something is going to be referenced frequently and you can alias it temporarily, when it will soon go out of scope and the alias will be cleaned up. If the code in Listing 4-6 were going to be run frequently, or if it contained many more calls to the types, it would probably be worth caching a reference to the type and avoid the repeated lookups. Creating a local alias is easy; just declare a variable and assign the type to it. Listing 4-7 demonstrates creating and using aliases for the Album and TributeAlbum types.

Listing 4-7

image from book
  var tributeAlbum = Wrox.ASPAJAX.Samples.TributeAlbum; var album = Wrox.ASPAJAX.Samples.Album; if(tributeAlbum.isInstanceOfType(anAlbum) == false) {     alert("anAlbum is not a TributeAlbum"); } if (tributeAlbum.isInstanceOfType(anotherAlbum) == true) {     alert("anotherAlbum is a TributeAlbum"); } if (tributeAlbum.inheritsFrom(album) == true) {     alert("TributeAlbum inherits from Album"); } if (album.inheritsFrom(tributeAlbum) == true) {     alert("Album does not inherit from TributeAlbum");  } 
image from book

The AJAX library provides a method for explicitly calling a base method implementation. This is often used when a derived type wants to take the result from the base type and modify it before returning it to the caller. It is not limited to calling into the base type from a derived type’s implementation. You can also call a base method for an object. In a language like C++, you can cast an object to its base type to access a specific method implementation. Likewise, this pattern in JavaScript lets you access the base method even though JavaScript can’t support the casting semantic for this purpose. In Listing 4-8 (from CallBase.aspx), the TributeAlbum class adds an override for the get_artist method. It calls the base implementation and then prepends it with "TRIBUTE: " before returning it. This is again a slight modification to the previous example of the example using Album and TributeAlbum types.

Listing 4-8

image from book
 Wrox.ASPAJAX.Samples.TributeAlbum.prototype = {     get_tributeArtist: function() {         return this._tributeArtist;     },     set_tributeArtist: function(tributeArtist) {         this._tributeArtist = tributeArtist;     },     get_artist: function() {         return ("TRIBUTE: " +          Wrox.ASPAJAX.Samples.TributeAlbum.callBaseMethod(this, "get_artist"));     } }
image from book

There are also several auxiliary functions for inspecting the types you create with the AJAX Library. You may not use them much in your application development, but it is interesting to see what can be done with the dynamic environment of JavaScript. The Type.parse function takes the name of a type, resolves it, and creates an instance of it. The Type.isClass function checks that an object has been registered with the type system. You can traverse and inspect object inheritance chains using the getName and getBaseType methods. Listing 4-9 (from BaseType.aspx) demonstrates checking that the object is an instance of a type registered with the ASP.NET AJAX type system and then gets the name of the base type from which it derives.

Listing 4-9

image from book
  var typeString = "Wrox.ASPAJAX.Samples.TributeAlbum"; var typeCheck = Type.parse(typeString); if(Type.isClass(typeCheck)) {     alert(typeCheck.getBaseType().getName()); } 
image from book

Using Interfaces

Interfaces are a convenient way to define standard behaviors that other types can implement. Although JavaScript has no built-in support for interfaces, Microsoft has developed a way to mimic interfaces in JavaScript. As in .NET, an interface is a contract that states that the implementer of the interface must provide all of the functionality specified in the interface. The interface itself is only a specification and has no functionality of its own. When a type declares that it implements an interface, you are assured of the set of features it offers. Types can use interfaces to establish contracts for behavior that can then be enforced at runtime.

Interface definitions follow the same pattern as creating classes shown in earlier examples. The function name is the name of the interface. The prototype of the function is modified to add the interface members. The convention in defining interface members is to throw Error.notImplemented for each member, so any class that implements the interface then needs to override the interface members to provide real implementations or the exception will be thrown. Enforcing that the class actually overrides every member is the sort of thing that would be caught during compilation with a .NET Framework language, but JavaScript has to detect these problems at runtime.

Listing 4-10 (from Interface.aspx) defines the IProvideTrackInfo interface with methods for getting the track count and the track listing. The registerInterface method is available on the type itself, just as the class methods were.

Listing 4-10

image from book
 <script type="text/javascript"> function pageLoad(sender, args) { Type.registerNamespace('Wrox.ASPAJAX.Samples'); Wrox.ASPAJAX.Samples.IProvideTrackInfo = function() {     throw Error.notImplemented(); } Wrox.ASPAJAX.Samples.IProvideTrackInfo.prototype = {     get_trackCount: function() {         throw Error.notImplemented();     },     get_tracks: function() {         throw Error.notImplemented();     }   }  Wrox.ASPAJAX.Samples.IProvideTrackInfo.registerInterface('Wrox.ASPAJAX.Samples. IProvideTrackInfo'); } </script> 
image from book

Obviously, when overriding the methods in a class that implements the interface, you wouldn’t want to call the base method and trigger the error!

Given a type, you can call getInterfaces to retrieve the complete set of interfaces that it implements. You can also check for a specific interface implementation by using the implementsInterface method on the type. Or you might need to check whether a type is itself an interface with isInterface. These are all operators on types, but there is also the isImplementedBy function, which takes an object instance and ascertains whether it is of a type that implements the interface.

For most development tasks, you will just define and use interfaces without using the methods for examining which objects implement what interfaces. But for more involved scenarios, the advanced functionality is useful. Listing 4-11 (also from Interface.aspx) shows the use of these methods on the IProvideTrackInfo interface. First, the Album class is modified to implement the interface.

Listing 4-11

image from book
 <script type="text/javascript"> Wrox.ASPAJAX.Samples.Album = function(title, artist) {     this._title = title;     this._artist = artist;     this._trackCount = 0;     this._tracks = null; } Wrox.ASPAJAX.Samples.Album.prototype = {     get_title: function() {         return this._title;     },     get_artist: function() {         return this._artist;     },     get_trackCount: function() {         return _trackCount;     },     get_tracks: function() {         return _tracks;     },     set_tracks: function(tracks) {         if(typeof(tracks) !== 'undefined'             _trackCount = tracks.length;             _tracks = tracks;         }     } }  Wrox.ASPAJAX.Samples.Album.registerClass('Wrox.ASPAJAX.Samples. Wrox.ASPAJAX.Samples.IProvideTrackInfo);  var album = new Wrox.ASPAJAX.Samples.Album('Rift', var tracks = new Array(15); tracks[0] = 'Rift'; tracks[1] = 'Fast Enough for You'; tracks[2] = 'Lengthwise'; tracks[3] = 'Maze'; tracks[4] = 'Sparkle'; tracks[5] = 'Horn'; tracks[6] = 'The Wedge'; tracks[7] = 'My Friend, My Friend'; tracks[8] = 'Weigh'; tracks[9] = 'All Things Reconsidered'; tracks[10] = 'Mound'; tracks[11] = "It's Ice"; tracks[12] = 'Lengthwise'; tracks[13] = 'The Horse'; tracks[14] = 'Silent In The Morning';  album.set_tracks(tracks);  alert(Wrox.ASPAJAX.Samples.Album.implementsInterface( Wrox.ASPAJAX.Samples.IProvideTrackInfo) === true); alert(Wrox.ASPAJAX.Samples.IProvideTrackInfo.isImplementedBy(album) === true); alert(Type.isInterface(Wrox.ASPAJAX.Samples.IProvideTrackInfo) === true); </script> 
image from book

Defining Enums and Flags

So far in this chapter, you have seen the Microsoft AJAX Library conventions for using namespaces, creating classes, and declaring interfaces as well as how to implement them. The last AJAX Library language feature I will cover is enumerations. The ASP.NET AJAX type system provides for defining enumerations and a specialized version of them used as combinable flags.

Enums let you establish a set of possible values. When using an enum, you know that it has to take on one of those values. Enum values are considered to be mutually exclusive. Colors are a typical example of an enum. If something is brown, it is not also green. (Sure, you could argue that something could be yellow and blue and thus green, but enums take a single value.) If the item is green, it is just green and nothing else from that enumeration.

In Listing 4-12 (from Enum.aspx), I define an enum for music genres. You can assign an album to be either Blues or Industrial, but you can’t make it be both Rock and Classical. I’m sure you can suggest something that is Classic Rock, but that is the point: an enum, by definition, can have only one value.

Listing 4-12

image from book
  <!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">     function pageLoad(sender, args) {         Type.registerNamespace('Wrox.ASPAJAX.         Wrox.ASPAJAX.Samples.MusicGenre = function() {             throw Error.invalidOperation();         }         Wrox.ASPAJAX.Samples.MusicGenre.prototype = {             Blues:            1,             Classical:        2,             Electronic:       3,             Folk:             4,             Industrial:       5,             Jazz:             6,             NewAge:           7,             HipHop:           8,             Rock:             9,             WorldFusion:     10         }         Wrox.ASPAJAX.Samples.MusicGenre.registerEnum('Wrox.ASPAJAX.Samples. MusicGenre');         var genre = Wrox.ASPAJAX.Samples.MusicGenre.Industrial;         alert(Wrox.ASPAJAX.Samples.MusicGenre.toString(genre)); //displays  Industrial         alert(genre === Wrox.ASPAJAX.Samples.MusicGenre.Industrial); //displays  'True'         genre = 22; //assign an invalid value         alert(Wrox.ASPAJAX.Samples.MusicGenre.toString(genre)); //displays an  error in debug mode                     }         </script> </head> <body>     <form  runat="server">         <div>     <asp:ScriptManager runat="server"  ScriptMode="Debug"  />     </div>     </form> </body> </html> 
image from book

At the end of Listing 4-12, the genre is assigned an integer that is not part of the enum. The AJAX Library doesn't see the assignment of an integer to a variable but can check when the value is treated as an enum when calling toString on it. Normally, the invalid value is just displayed as an empty string, but Microsoft has added a terrific new feature to help you diagnose problems in JavaScript code: When you enable debugging by setting debug="true" in the compilation section of your web.config file (which is the typical setting on developer’s computers), more detailed information is produced. Figure 4-1 shows the dialog that Internet Explorer displays for this error when running in debug mode.

image from book
Figure 4-1

Firefox also shows the error in the JavaScript console, if you have selected to show it from the Tools menu. The error message from Firefox is shown in Figure 4-2.

image from book
Figure 4-2

Flags are a specialized type of enum. In fact, they are so similar that ASP.NET AJAX does not define a separate type for flags. You create and register a flags type the same way you create an enum, but the call to registerClass takes an additional parameter for indicating that the enum registration should be treated the same way as registering flags. By defining the enum as supporting flags, the behavior is distinctly different.

When an enum is declared as supporting flags, the values assigned to it are tracked as individual entries instead of as a single distinct value. If you use the logical OR operator (|) to combine enum values, what you have is the single enum value that is the sum of the parts.

 genre = Wrox.ASPAJAX.Samples.MusicGenre.Blues | Wrox.ASPAJAX.Samples.MusicGenre.Classical; alert(Wrox.ASPAJAX.Samples.MusicGenre.toString(genre));

Combining Blues, with an enum value of 1, and Classical, with an enum value of 2, results in a variable with a value of 3. The enum for MusicGenre treats that as Electronic (the enum for a value of 3) and a toString call displays the same. I would be hard-pressed to come up with an example of music that is Electronic, Classical, and Blues all at the same time!

The combined value is still within the allowable range of values for the MusicGenre enum, so no error is encountered. However, since enums are ultimately supposed to designate a single value, you do get an error when defining a value that exceeds the defined range. If I decide that something is Electronic and Rock, the combination results in an error. Three plus nine is greater than the WorldFusion top value of ten. When debug is set to true, any attempt to display the value will result in an error.

Important 

The debug version of the ASP.NET AJAX scripts provides valuable help in writing robust and resilient code. The debug scripts will alert you to passing invalid parameters, exceeding boundary conditions, and even using variables as types other than they are declared. However, in order to do this extra error-checking, the debug scripts are much larger and execute much more slowly than the release version. Always ensure that debugging is disabled on live deployments. ASP.NET provides a catch-all setting to ensure that optional settings are right for deployment. Setting retail to true overrides other debugging and trace settings that are useful during development but adversely affect performance at runtime. Chapter 9 addresses this issue in more detail.

  <system.web> <deployment retail="true" /> </system.web> 

In Listing 4-13 (Flags.aspx), I define some music categories for which multiple values make sense. Music doesn’t necessarily need to be assigned to just one of these personal categories. There is music that I like to listen to while running and driving but that is too distracting for coding time. There is holiday music that I would listen to while hosting a party, but it would not provide motivation for running an extra mile or two.

Listing 4-13

image from book
 <%@ Page Debug="true" %> <!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>ASP.NET AJAX Flags</title>     <script type="text/javascript">     function pageLoad(sender, args) {         Type.registerNamespace('Wrox.ASPAJAX.         Wrox.ASPAJAX.Samples.MyCategory = function() {             throw Error.invalidOperation();         }         Wrox.ASPAJAX.Samples.MyCategory.prototype = {             Running: 1,             Driving: 2,             Dinner: 4,             Holiday: 8,             Entertaining: 16,              Coding: 32         }         Wrox.ASPAJAX.Samples.MyCategory.registerEnum('Wrox.ASPAJAX. Samples.MyCategory', true);         var category = Wrox.ASPAJAX.Samples.MyCategory.Running |             Wrox.ASPAJAX.Samples.MyCategory.Driving |              Wrox.ASPAJAX.Samples.MyCategory.Coding;         alert(Wrox.ASPAJAX.Samples.MyCategory.toString(category));         var myCategory = Wrox.ASPAJAX.Samples.MyCategory;         if(category & myCategory.Running)             alert("Running")         if(category & myCategory.Driving)             alert("Driving");         if(category & myCategory.Dinner)             alert("Dinner");         if(category & myCategory.Holiday)             alert("Holiday");         if(category & myCategory.Entertaining)             alert("Entertaining")         if(category & myCategory.Coding)             alert("Coding");     }         </script> </head> <body>     <form  runat="server">         <div>     <asp:ScriptManager runat="server"  />     </div>     </form> </body> </html> 
image from book

The toString call on the flag reveals that the AJAX Library has tracked the set of combined flags. No longer is the result treated as a single value. Instead, the set of values are displayed: Running, Driving, and Coding. Notice that the individual values for flag elements follow the pattern of doubling. This enables the combination semantics in the same way that flags operate at the bit level.




Professional ASP. NET 2.0 AJAX
Professional ASP.NET 2.0 AJAX (Programmer to Programmer)
ISBN: 0470109629
EAN: 2147483647
Year: 2004
Pages: 107

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net