Building Basic Components


Let's start by building a super simple component. The HelloWorld component is contained in Listing 14.1.

Listing 14.1. HelloWorld.vb

Public Class HelloWorld     Public Function SayMessage() As String         Return "Hello World!"     End Function End Class

Visual Web Developer Note

When using Visual Web Developer, you create a component by selecting the menu option Website, Add New Item, and then selecting the Class item (see Figure 14.1). The first time you add a component to a project, Visual Web Developer prompts you to create a new folder named App_Code. You want your new component to be added to this folder.

Figure 14.1. Creating a new component with Visual Web Developer.



The HelloWorld component consists of a single method named SayMessage() which returns the string Hello World!.

Make sure that you save the HelloWorld.vb file to your application's App_Code folder. If you don't save the component to this folder, then you won't be able to use the component in your pages.

Next, you need to create a page that uses the new component. This page is contained in Listing 14.2.

Listing 14.2. ShowHelloWorld.aspx

<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server">     Sub Page_Load()         Dim objHelloWorld As New HelloWorld()         lblMessage.Text = objHelloWorld.SayMessage()     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Show Hello World</title> </head> <body>     <form  runat="server">     <div>     <asp:Label                  Runat="server" />     </div>     </form> </body> </html>

In the Page_Load() event handler, an instance of the HelloWorld component is created. Next, the result returned by a call to the SayMessage() method is assigned to a Label control. When you open the page in your browser, you'll see the message Hello World!.

Notice how simple this process of creating the component is. You don't need to perform any special registration and you don't need to compile anything explicitly. Everything just works magically.

Components and Dynamic Compilation

You are not required to explicitly compile (build) the component because the ASP.NET Framework automatically compiles the component for you. Any component that you add to the App_Code folder is compiled dynamically in the same way as an ASP.NET page. If you add a new component to the App_Code folder and request any page from your website, the contents of the App_Code folder are compiled into a new assembly and saved to the Temporary ASP.NET Files folder, located at the following path:

C:\WINDOWS\Microsoft.NET\Framework\[version]\ Temporary ASP.NET Files\[application name] 


Whenever you modify the component, the existing assembly in the Temporary ASP.NET Files folder is deleted. The App_Code folder is compiled again when you make a new page request.

Note

An assembly is the dll file (or dll files) in which components are stored.


You can add as many subfolders to the App_Code folder as you need to organize your components. The ASP.NET Framework finds your component no matter how deeply you nest the component in a subfolder.

One significant drawback of this process of dynamic compilation is that any errors in any component contained in the App_Code folder prevent any pages from executing. Even if a page does not use a particular component, any syntax errors in the component raise an exception when you request the page.

Tip

If a component contains an error, and you want to temporarily hide the component from the ASP.NET Framework, change the file extension to an extension that the ASP.NET Framework does not recognize, such as HelloWorld.vb.exclude. Visual Web Developer uses this method to hide a component when you right-click a component and select the menu option Exclude From Project.


Mixing Different Language Components in the App_Code Folder

You don't have to do anything special, just as long as all the components in the App_Code folder are written in the same language. For example, if you use Visual Basic .NET to create all your components, then the ASP.NET Framework automatically infers the language of your components and everything just works.

However, if you mix components written in more than one language in the App_Code folderfor example, Visual Basic .NET, and C#then you must perform some extra steps.

First, you need to place components written in different languages in different subfolders. You can name the subfolders anything you want. The point is to not mix different language components in the same folder.

Furthermore, you need to modify your web configuration file to recognize the different subfolders. For example, if you create two subfolders in the App_Code folder named VBCode and CSCode, then you can use the web configuration file in Listing 14.3 to use components written in both VB.NET and C#.

Listing 14.3. Web.Config

<?xml version="1.0"?> <configuration>   <system.web>     <compilation>     <codeSubDirectories>       <add directoryName="VBCode" />       <add directoryName="CSCode" />     </codeSubDirectories>     </compilation>   </system.web> </configuration>

When the contents of the App_Code folder are compiled, two assemblies are created: one that corresponds to the VBCode folder and one that corresponds to the CSCode folder. Notice that you don't need to indicate the language used for each folderthe ASP.NET Framework infers the language for you.

There is nothing wrong with mixing components written in different languages in the same ASP.NET page. After a component is compiled, the .NET Framework treats VB.NET and C# components in the same way.

Declaring Methods

The simple HelloWorld component in Listing 14.1 contains a single method named SayMessage(), which returns a string value. When writing components with Visual Basic .NET, you create methods by creating either a subroutine or a function. Use a subroutine when a method does not return a value, and use a function when a method does return a value.

The SayMessage() method in Listing 14.1 is an instance method. In other words, you must create a new instance of the HelloWorld class before you can call the SayMessage(), method like this:

Dim objHelloWorld As New HelloWorld() lblMessage.Text = objHelloWorld.SayMessage() 


In the first line, a new instance of the HelloWorld component is created. The SayMessage() method is called from this instance. For this reason, the SayMessage() method is an instance method.

As an alternative to creating an instance method, you can create a shared method. The advantage of a shared method is that you do not need to create an instance of a component before calling it. For example, the SayMessage() method in the modified HelloWorld component in Listing 14.4 is a shared method.

Note

Shared methods are called static methods in other languages such as C# and Java.


Listing 14.4. SharedHelloWorld.vb

Public Class SharedHelloWorld     Public Shared Function SayMessage() As String         Return "Hello World!"     End Function End Class

The SharedHelloWorld component defined in Listing 14.3 is exactly the same as the HelloWorld component created in Listing 14.1 with one change: The SayMessage() method includes a Shared modifier.

The page in Listing 14.5 uses the SharedHelloWorld component to display the Hello World! message.

Listing 14.5. ShowSharedHelloWorld.aspx

<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server">     Sub Page_Load()         lblMessage.Text = SharedHelloWorld.SayMessage()     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Show Shared Hello World</title> </head> <body>     <form  runat="server">     <div>     <asp:Label                  Runat="server" />     </div>     </form> </body> </html>

Notice that the page in Listing 14.5 does not create an instance of the SharedHelloWorld component. The SayMessage() method is called directly from the SharedHelloWorld class.

The advantage of using shared methods is that they save you typing. You don't have to go through the pain of instantiating a component before calling the method. Many classes in the .NET Framework include shared methods. For example, the String.Format() method, the Int32.Parse() method, and the DateTime.DaysInMonth() method are all shared methods.

There is nothing wrong with mixing both shared and instance methods in the same component. For example, you might want to create a Product component that has a shared GetProducts() method and an instance SaveProduct() method.

The one significant limitation of using a shared method is that a shared method cannot refer to an instance field or property. In other words, shared methods should be stateless.

Declaring Fields and Properties

You can define a property for a component in two ways: the lazy way and the virtuous way.

The lazy way to create a property is to create a public field. If you declare any field with the Public access modifier, then the field can be accessed from outside the component.

For example, the component in Listing 14.6 contains a public field named Message.

Listing 14.6. FieldHelloWorld.vb

Public Class FieldHelloWorld     Public Message As String     Public Function SayMessage() As String         Return Message     End Function End Class

The Message field is declared near the top of the FieldHelloWorld class definition. Notice that the Message field is returned by the SayMessage() method.

The page in Listing 14.7 uses the FieldHelloWorld component to display a message.

Listing 14.7. ShowFieldHelloWorld.aspx

<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server">     Sub Page_Load()         Dim objFieldHelloWorld As New FieldHelloWorld()         objFieldHelloWorld.Message = "Good Day!"         lblMessage.Text = objFieldHelloWorld.SayMessage()     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Show Field Hello World</title> </head> <body>     <form  runat="server">     <div>     <asp:Label                  Runat="server" />     </div>     </form> </body> </html>

In the Page_Load() event handler in Listing 14.7, an instance of the FieldHelloWorld class is created, a value is assigned to the Message field, and the SayMessage() method is called.

There are a couple of serious disadvantages to creating properties by creating public fields. First, the .NET Framework recognizes properties as separate entities. Several methods in the .NET Framework recognize properties but not fields.

For example, you can refer to component properties and not fields when using the Eval() method in a databinding expression. If you want to bind a collection of Product objects to a GridView control, then you should expose the properties of the Product component as true properties and not as fields.

The other disadvantage of fields is that they do not provide you with a chance to validate the value being assigned to the field. For example, imagine that a property represents a database column and the column accepts no more than five characters. In that case, you should check whether the value being assigned to the property is less than five characters.

The component in Listing 14.8 uses a property instead of a field. (It does things the virtuous way.)

Listing 14.8. PropertyHelloWorld.vb

Imports System Public Class PropertyHelloWorld     Private _message As String     Public Property Message() As String         Get             Return _message         End Get         Set(ByVal Value As String)             If Value.Length > 5 Then                 Throw New Exception("Message too long!")             End If             _message = Value         End Set     End Property     Public Function SayMessage() As String         Return _message     End Function End Class

Notice that the component in Listing 14.8 contains a property named Message and a private backing field named _message. The Message property contains both a Get() and a Set() function. The Get() function is called when you read the value of the Message property, and the Set() function is called when you assign a value to the Message property.

The Get() function simply returns the value of the private _message field. The Set() function assigns a value to the private _message field. The Set() function throws an exception if the length of the value being assigned to the _message field exceeds five characters.

Note

In Listing 14.8, the private field is named _message. The underscore character (_) has no programmatic significance. By convention, private members of a class are named with a leading underscore, but there is nothing wrong with following some other convention.


The page in Listing 14.9 uses the PropertyHelloWorld component.

Listing 14.9. ShowPropertyHelloWorld.aspx

<%@ Page Language="VB" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server">     Sub Page_Load()         Dim objPropertyHelloWorld As New PropertyHelloWorld()         objPropertyHelloWorld.Message = "Hello World!"         lblMessage.Text = objPropertyHelloWorld.SayMessage()     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <title>Show Property Hello World</title> </head> <body>     <form  runat="server">     <div>     <asp:Label                  Runat="server" />     </div>     </form> </body> </html>

If you open the page in Listing 14.9 in your web browser, you will get a big, fat error message (see Figure 14.2). Because a string longer than 5 characters is assigned to the Message property in the Page_Load() method, the Message property raises an exception.

Figure 14.2. Assigning more than five characters.


You can also create read-only properties when the situation warrants it. For example, the component in Listing 14.10 returns the current server time. It would not make sense to assign a value to this property, so the property is declared as read-only.

Listing 14.10. ServerTime.vb

Public Class ServerTime     Public ReadOnly Property CurrentTime() As String         Get             Return DateTime.Now.ToString()         End Get     End Property End Class

Note

You can create shared fields and properties in the same way as you create shared methods, by using the Shared keyword. Any value you assign to a shared field or property is shared among all instances of a component.

I recommend that you avoid using shared fields and properties when building ASP.NET applications. Using shared fields and properties raises nasty concurrency issues in a multi-threaded environment such as ASP.NET. If you insist on creating a shared property, make the property read-only.


Declaring Constructors

A constructor is a special class method that is called automatically when you create a new instance of a class. Typically, you use the constructor to initialize private fields contained in the class.

When creating a constructor in Visual Basic .NET, you create a public subroutine named New(). For example, the class in Listing 14.11 displays a random quotation (see Figure 14.3). The collection of random quotations is created in the component's constructor.

Listing 14.11. Quote.vb

[View full width]

Imports System.Collections.Generic Public Class Quote     Private _quotes As New List(Of String)     Public Function GetQuote() As String         Dim rnd As New Random()         Return _quotes(rnd.Next(_quotes.Count))     End Function     Public Sub New()         _quotes.Add("All paid jobs absorb and degrade the mind -- Aristotle")         _quotes.Add("No evil can happen to a good man, either in life or after death --  Plato")         _quotes.Add("The only good is knowledge and the only evil is ignorance -- Plato")     End Sub End Class

Figure 14.3. Displaying a random quotation.


Notice that the collection named _quotes is declared in the body of the class. That way, you can refer to the _quotes field in both the constructor and the GetQuote() method.

Note

You can create shared constructors by using the Shared keyword when declaring a constructor. A shared constructor is called once before any instance constructors.


Overloading Methods and Constructors

When a method is overloaded, a component contains two methods with exactly the same name. Many methods in the .NET Framework are overloaded, including the String.Replace() method, the Random.Next() method, and the Page.FindControl() method.

For example, here is a list of the three overloaded versions of the Random.Next() method:

  • Next() Returns a random number between 0 and 2,147,483,647.

  • Next(upperbound) Returns a number between 0 and the upper bound.

  • Next(lowerbound, upperbound) Returns a number between the lower bound and the upper bound.

Because all three methods do the same thingthey all return a random numberit makes sense to overload the Next() method. The methods differ only in their signatures. A method signature consists of the order and type of parameters that a method accepts. For example, you can't overload two methods that have exactly the same set of parameters (even if the names of the parameters differ).

Overloading is useful when you want to associate related methods. Overloading is also useful when you want to provide default values for parameters. For example, the StoreProduct component in Listing 14.12 contains three overloaded versions of its SaveProduct() method.

Listing 14.12. StoreProduct.vb

[View full width]

Public Class StoreProduct     Public Sub SaveProduct(ByVal name As String)         SaveProduct(name, 0, String.Empty)     End Sub     Public Sub SaveProduct(ByVal name As String, ByVal price As Decimal)         SaveProduct(name, price, String.Empty)     End Sub     Public Sub SaveProduct(ByVal name As String, ByVal price As Decimal, ByVal description  As String)         ' Save name, price, description to database     End Sub End Class

You can call any of the three SaveProduct() methods in Listing 14.12 to save a new product. You can supply the new product with a name, a name and a price, or a name and a price and a description.

Visual Web Developer Note

When typing an overloaded method in Source view, the Intellisense pops up with all the different sets of parameters that you can use with the overloaded method. See Figure 14.4.

Figure 14.4. Typing an overloaded method in Visual Web Developer.



Because a constructor is just a special method, you also can use overloading when declaring constructors for a class. For example, the ProductConstructor class in Listing 14.13 contains three overloaded constructors that can be used to initialize the Product class.

Listing 14.13. ProductConstructor.vb

Public Class ProductConstructor     Public Sub New(ByVal name As String)         Me.New(name, 0, String.Empty)     End Sub     Public Sub New(ByVal name As String, ByVal price As Decimal)         Me.New(name, price, String.Empty)     End Sub     Public Sub New(ByVal name As String, ByVal price As Decimal, ByVal description As String)         ' Use name, price, and description     End Sub End Class

When you instantiate the component in Listing 14.13, you can instantiate it in any of the following ways:

Dim objProduct As New ProductConstructor("Milk") Dim objProduct As New ProductConstructor("Milk", 2.99D) Dim objProduct As New ProductConstructor("Milk", 2.99D, "Whole Milk") 


Declaring Namespaces

A namespace enables you to group logically related classes. You are not required to provide a class with a namespace. To this point, all the components that we have created have been members of the global namespace. However, several advantages result from grouping components into namespaces.

First, namespaces prevent naming collisions. If two companies produce a component with the same name, then namespaces provide you with a method of distinguishing the components.

Second, namespaces make it easier to understand the purpose of a class. If you group all your data access components into a DataAccess namespace and all your business logic components in a BusinessLogic namespace, then you can immediately understand the function of a particular class.

In an ASP.NET page, you import a namespace like this:

<%@ Import Namespace="System.Collections" %> 


In a Visual Basic component, on the hand, you import a namespace like this:

Imports System.Collections 


You can create your own custom namespaces and group your components into namespaces by using the Namespace statement. For example, the component in Listing 14.13 is contained in the AspUnleashed.SampleCode namespace.

Listing 14.14. Namespaced.vb

Namespace AspNetUnleashed.SampleCode     Public Class Namespaced         Public Function SaySomething() As String             Return "Something"         End Function     End Class End Namespace

The file in Listing 14.14 uses the Namespace statement to group the Namespaced component into the AspUnleashed.SampleCode namespace. Components in different files can share the same namespace, and different components in the same file can occupy different namespaces.

The periods in a namespace name have no special significance. The periods are used to break up the words in the namespace, but you could use another character, such as an underscore character, instead.

Microsoft recommends a certain naming convention when creating namespaces:

CompanyName.TechnologyName[.Feature][.Design] 


So, if your company is named Acme Consulting and you are building a data access component, you might add your component to the following namespace:

AcmeConsulting.DataAccess 


Of course this is simply a naming convention. No serious harm will come to you if you ignore it.

Creating Partial Classes

You can define a single component that spans multiple files by taking advantage of a new feature of the .NET 2.0 Framework called partial classes.

For example, the files in Listings 14.15 and 14.16 contain two halves of the same component.

Listing 14.15. FirstHalf.vb

Partial Public Class Tweedle     Private _message As String = "THEY were standing under a tree," _         & "each with an arm round the other's neck, and Alice knew" _         & "which was which in a moment, because one of them had" _         & """DUM"" embroidered on his collar, and the other ""DEE""." End Class

Listing 14.16. SecondHalf.vb

Partial Public Class Tweedle     Public Function GetMessage() As String         Return _message     End Function End Class

Notice that the private _message field is defined in the first file, but this private field is used in the GetMessage() method in the second file. When the GetMessage() method is called, it returns the value of the private field from the other class.

Both files define a class with the same name. The class declaration includes the keyword Partial. The Partial keyword marks the classes as partial classes.

Note

Partial classes are the basis for code-behind pages in the ASP.NET Framework. The code-behind file and the presentation page are two partial classes that get compiled into the same class.


Inheritance and MustInherit Classes

When one class inherits from a second class, the inherited class automatically includes all the non-private methods and properties of its parent class. In other words, what's true of the parent is true of the child, but not the other way around.

Inheritance is used throughout the .NET Framework. For example, every ASP.NET page inherits from the base System.Web.UI.Page class. The only reason that you can use properties such as the IsPostback property in an ASP.NET page is that the page derives from the base Page class.

All classes in the .NET Framework derive from the base System.Object class. The Object class is the great-grandmother of every other class. This means that any methods or properties of the Object class, such as the ToString() method, are shared by all classes in the Framework.

You can take advantage of inheritance when building your own components. You indicate that one class inherits from a second class by using the Inherits keyword.

For example, the file in Listing 14.17 includes three components: a BaseProduct class, a ComputerProduct class, and a TelevisionProduct class.

Listing 14.17. Inheritance.vb

Public Class BaseProduct     Private _price As Decimal     Public Property Price() As Decimal         Get             Return _price         End Get         Set(ByVal Value As Decimal)             _price = Value         End Set     End Property End Class Public Class ComputerProduct     Inherits BaseProduct     Private _processor As String     Public Property Processor() As String         Get             Return _processor         End Get         Set(ByVal Value As String)             _processor = value         End Set     End Property End Class Public Class TelevisionProduct     Inherits BaseProduct     Private _isHDTV As Boolean     Public Property IsHDTV() As Boolean         Get             Return _isHDTV         End Get         Set(ByVal Value As Boolean)             _isHDTV = value         End Set     End Property End Class

Notice that both the ComputerProduct and TelevisionProduct components inherit from the BaseProduct component. Because the BaseProduct class includes a Price property, both inherited components automatically inherit this property.

When inheriting one class from another, you also can override methods and properties of the base class. Overriding a method or property is useful when you want to modify the behavior of an existing class.

To override a property or method of a base class, the property or method must be marked with the Visual Basic .NET Overridable or MustOverride keyword. Only methods or properties marked with the Overridable or MustOverride keyword can be overridden.

For example, the file in Listing 14.18 contains two components: a ProductBase class and a OnSaleProduct class. The second class inherits from the first class and overrides its Price property. The Price property of the OnSaleProduct component divides the price by half.

Listing 14.18. OnSaleProduct.vb

Public Class ProductBase     Private _price As Decimal     Public Overridable Property Price() As Decimal         Get             Return _price         End Get         Set(ByVal Value As Decimal)             _price = value         End Set     End Property End Class Public Class OnSaleProduct     Inherits ProductBase     Public Overrides Property Price() As Decimal         Get             Return MyBase.Price / 2         End Get         Set(ByVal Value As Decimal)             MyBase.Price = value         End Set     End Property End Class

Notice that the MyBase keyword is used in Listing 14.18 to refer to the base class (the ProductBase class).

Finally, you can use the MustInherit keyword when declaring a class to mark the class as an abstract class. You cannot instantiate a MustInherit class. To use a MustInherit class, you must derive a new class from the MustInherit class and instantiate the derived class.

MustInherit classes are the foundation for the ASP.NET 2.0 Provider Model. Personalization, Membership, Roles, Session State, and Site Maps all use the Provider Model.

For example, the MembershipProvider class is the base class for all Membership Providers. The SqlMembershipProvider and ActiveDirectoryMembershipProvider classes both derive from the base MembershipProvider class.

Note

Chapter 21, "Using ASP.NET Membership," discusses the MembershipProvider classes in detail. The MembershipProvider is responsible for saving and loading membership information such as application usernames and passwords.


The base MembershipProvider class is a MustInherit class. You cannot use this class directly in your code. Instead, you must use one of its derived classes. However, the base MembershipProvider class provides a common set of methods and properties that all MembershipProvider-derived classes inherit.

The base MembershipProvider class includes a number of methods and properties marked as MustOverride. A derived MembershipProvider class is required to override these properties and methods.

The file in Listing 14.18 contains two components. The first component, the BaseEmployee component, is a MustInherit class that contains a MustOverride property named Salary. The second component, the SalesEmployee, inherits the BaseEmployee component and overrides the Salary property.

Listing 14.18. Employees.vb

Public MustInherit Class BaseEmployee     Public MustOverride ReadOnly Property Salary() As Decimal     Public ReadOnly Property Company() As String         Get             Return "Acme Software"         End Get     End Property End Class Public Class SalesEmployee     Inherits BaseEmployee     Public Overrides ReadOnly Property Salary() As Decimal         Get             Return 67000.23D         End Get     End Property End Class

Declaring Interfaces

An interface is a list of properties and methods that a class must implement. If a class implements an interface, then you know that the class includes all the properties and methods contained in the interface.

For example, the file in Listing 14.19 contains an interface named IProduct and two components named MusicProduct and BookProduct.

Listing 14.19. Products.vb

Public Interface IProduct     ReadOnly Property Price() As Decimal     Sub SaveProduct() End Interface Public Class MusicProduct     Implements IProduct     Public ReadOnly Property Price() As Decimal Implements IProduct.Price         Get             Return 12.99D         End Get     End Property     Public Sub SaveProduct() Implements IProduct.SaveProduct         ' Save Music Product     End Sub End Class Public Class BookProduct     Implements IProduct     Public ReadOnly Property Price() As Decimal Implements IProduct.Price         Get             Return 23.99D         End Get     End Property     Public Sub SaveProduct() Implements IProduct.SaveProduct         ' Save Book Product     End Sub End Class

The declaration of both components in Listing 14.17 includes the Implements keyword. Both components implement the IProduct interface. Notice, furthermore, that both the SaveProduct() method and the Price property include an Implements clause. The Implements clause associates a method or property in the derived class with a method or property contained in the interface.

Interfaces are similar to MustInherit classes with two important differences. First, a component can inherit from only one class. On the other hand, a component can implement many different interfaces.

Second, a MustInherit class can contain application logic. You can add methods to a MustInherit class that all derived classes inherit and can use. An interface, on the other hand, cannot contain any logic. An interface is nothing more than a list of methods and properties.

Using Access Modifiers

Visual Basic .NET supports the following access modifiers (also called access levels), which you can use when declaring a class, method, or property:

  • Public A Public class, method, or property has no access restrictions.

  • Protected A Protected method or property can be accessed only within the class itself or a derived class.

  • Friend A Friend class, method, or property can be accessed only by a component within the same assembly (dll file). Because ASP.NET pages are compiled into different assemblies than the contents of the App_Code folder, you cannot access a Friend member of a class outside of the App_Code folder.

  • Protected Friend A Protected Friend method or property can be accessed within the class itself or a derived class, or any other class located in the same assembly.

  • Private A Private class, method, or property can be accessed only within the class itself.

Using access modifiers is useful when you are developing a component library that might be used by other members of your development team (or your future self). For example, you should mark all methods that you don't want to expose from your component as private.

Intellisense and Components

Visual Web Developer automatically pops up with Intellisense when you type the names of classes, properties, or methods in Source view. You can add Intellisense to your custom components to make it easier for other developers to use your components.

If you add XML comments to a component, then the contents of the XML comments appear automatically in Intellisense. For example, the component in Listing 14.20 includes XML comments for its class definition, property definitions, and method definition (see Figure 14.5).

Figure 14.5. Adding comments to a component.


Listing 14.20. Employee.vb

''' <summary> ''' Represents an employee of Acme.com ''' </summary> Public Class Employee     Private _firstName As String     Private _lastName As String     ''' <summary>     ''' The employee first name     ''' </summary>     Public ReadOnly Property FirstName() As String         Get             Return _firstName         End Get     End Property     ''' <summary>     ''' The employee last name     ''' </summary>     Public ReadOnly Property LastName() As String         Get             Return _lastName         End Get     End Property     ''' <summary>     ''' Returns an employee from the database     ''' </summary>     ''' <param name="id">The unique employee identifier</param>     ''' <returns>An instance of the Employee class</returns>     Public Shared Function getEmployee(ByVal id As Integer) As Employee         Return Nothing     End Function     ''' <summary>     ''' Initializes an employee     ''' </summary>     ''' <param name="firstName">First Name</param>     ''' <param name="lastName">Last Name</param>     Public Sub New(ByVal firstName As String, ByVal lastName As String)         _firstName = firstName         _lastName = lastName     End Sub End Class

Note

You can generate an XML documentation filea file that contains all the XML commentsfor the components contained in a folder by using the /doc switch with the Visual Basic command-line compiler. The Visual Basic command-line compiler is discussed in the second part of this chapter, "Building Component Libraries."


Using ASP.NET Intrinsics in a Component

When you add code to an ASP.NET page, you are adding code to an instance of the Page class. The Page class exposes several ASP.NET intrinsic objects such as the Request, Response, Cache, Session, and trace objects.

If you want to use these objects within a component, then you need to do a little more work. Realize that when you create a component, you are not creating an ASP.NET component. In this chapter, we are creating .NET components, and a .NET component can be used by any type of .NET application, including a Console application or Windows Forms application.

To use the ASP.NET instrinsics in a component, you need to get a reference to the current HtppContext. The HttpContext object is the one object that is available behind the scenes through the entire page processing lifecycle. You can access the HttpContext object from any user control, custom control, or component contained in a page.

Note

The HttpContext object includes an Items collection. You can add anything to the Items collection and share the thing among all the elements contained in a page.


To get a reference to the current HttpContext object, you can use the shared Current property included in the HttpContext class. For example, the component in Listing 14.21 uses the HttpContext object to use both the Session and trace objects.

Listing 14.21. Preferences.vb

Imports System.Web Public Class Preferences     Public Shared Property FavoriteColor() As String         Get             Dim context As HttpContext = HttpContext.Current             context.Trace.Warn("Getting FavoriteColor")             If context.Session("FavoriteColor") Is Nothing Then                 Return "Blue"             Else                 Return CType(context.Session("FavoriteColor"), String)             End If         End Get         Set(ByVal Value As String)             Dim context As HttpContext = HttpContext.Current             context.Trace.Warn("Setting FavoriteColor")             context.Session("FavoriteColor") = value         End Set     End Property End Class

The Preferences component contains a single property named FavoriteColor. The value of this property is stored in Session state. Anytime this property is modified, the TRace object writes a warning.

You can use the Preferences component in the page contained in Listing 14.22.

Listing 14.22. ShowPreferences.aspx

<%@ Page Language="VB" trace="true" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server">     Sub Page_PreRender()         body1.Style("background-color") = Preferences.FavoriteColor     End Sub     Protected Sub btnSelect_Click(ByVal sender As Object, ByVal e As EventArgs)         Preferences.FavoriteColor = ddlFavoriteColor.SelectedItem.Text     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <style type="text/css">         .content         {             width:80%;             padding:20px;             background-color:white;         }     </style>     <title>Show Preferences</title> </head> <body  runat="server">     <form  runat="server">     <div >     <h1>Show Preferences</h1>     <asp:DropDownList                  Runat="server">         <asp:ListItem Text="Blue" />         <asp:ListItem Text="Red" />         <asp:ListItem Text="Green" />     </asp:DropDownList>     <asp:Button                  Text="Select"         Runat="server" OnClick="btnSelect_Click" />     </div>     </form> </body> </html>

After you open the page in Listing 14.22, you can select your favorite color from the DropDownList control. Your favorite color is stored in the Preferences object (see Figure 14.6).

Figure 14.6. Selecting a favorite color.





ASP. NET 2.0 Unleashed
ASP.NET 2.0 Unleashed
ISBN: 0672328232
EAN: 2147483647
Year: 2006
Pages: 276

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