Chapter 20. Building Business Components

In this chapter, you’ll learn how to create custom components with C# and Visual Basic .NET. Components enable you to reuse the same application logic—the same code—across multiple pages. You can place any type of application logic in a component that you want. For example, you can place all of your database access logic in a component, you can expose an XML Web service from a component, or you can implement custom business logic in a component.

In this chapter, you will learn

  • The advantages of using components in your Web applications

  • How to create simple components

  • How to retrieve database data in a component

  • How to package components in reusable class libraries

  • How to access intrinsic ASP.NET objects in components such as the Cache, Trace, and Session objects

Why Use Components?

Before we get started building components, we should pause for a moment and consider whether building components is really necessary. Why bother? What advantages do we get by separating our application into components?

One important advantage of using components is that they enable you to reuse the same application logic across multiple pages. For example, if you need to execute a complicated function to perform a tax calculation on multiple pages, you can place the function in a single component and call the very same function from multiple pages.

Tip

Even if you just think that you might want to use the same logic elsewhere, it’s a good idea to package the logic into a separate component. You don’t want to waste time extracting code from existing applications when, all of a sudden, you discover that you need to reuse the code.

Another important advantage of using components is that they enable you to isolate changes that might occur in one part of an application from other parts of an application. In other words, components can make your applications less brittle.

For example, suppose that you build an application that displays sales data. Furthermore, suppose that when you created the application, you stored all the data in an Oracle database. One fine day, a decision is made to transfer all the data from the Oracle database to an SQL Server database.

If you coded all of your database access functions directly into your Web Form Pages, you would need to go back and alter all of the pages. If, on the other hand, you separated the data access functions into a set of data access components, you could modify the components without touching a single Web Form Page or any other part of your application’s business logic.

Finally, placing your application logic into separate components makes it easier for multiple developers to work on a project at the same time. If you divide an application into multiple components, each developer can focus on implementing a particular part of an application without worrying about stumbling over the work of other developers.

For simple applications, you might never need to use components. However, as your applications grow more complicated, dividing your applications into components can make your life significantly easier.

Tip

Creating components also makes it easier to build scaffolding during development, for example, quickly putting together a component that returns a sample value allows you to build around it before it’s implemented.

Components Versus Classes

Visual Studio .NET enables you to add two types of entities related to classes to your projects. You can add a C# or Visual Basic .NET component to your project by selecting Add Component from the Project menu, or you can add a C# or Visual Basic .NET class to your project by selecting Add Class from the Project menu.

The only difference between components and classes is that components support the Visual Studio .NET designer interface better than classes. Because components provide you with more flexibility, we’ll build our custom components in this chapter by using components.

Adding a class to your project adds a file with the skeleton for a class declaration. The file automatically contains the following code:

C#

using System;

namespace myApp
{
  /// <summary>
  /// Summary description for Class1.
  /// </summary>
  public class Class1
  {
    public Class1()
    {
      //
      // TODO: Add constructor logic here
      //
    }
  }
}

VB.NET

Public Class Class1

End Class

A component is similar to a class. When you add a new component to a project, the file for the component automatically contains the following code:

C#

using System;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;

namespace myApp
{
  /// <summary>
  /// Summary description for Component.
  /// </summary>
  public class Component : System.ComponentModel.Component
  {
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.Container components = null;

    public Component(System.ComponentModel.IContainer container)
    {
      /// <summary>
      /// Required for Windows.Forms Class Composition Designer support
      /// </summary>
      container.Add(this);
      InitializeComponent();

      //
      // TODO: Add any constructor code after InitializeComponent call
      //
    }

    public Component()
    {
      /// <summary>
      /// Required for Windows.Forms Class Composition Designer support
      /// </summary>
      InitializeComponent();

      //
      // TODO: Add any constructor code after InitializeComponent call
      //
    }
  }
}

VB.NET

Public Class Component1
    Inherits System.ComponentModel.Component

End Class

You’ll notice that the declaration for a component includes some extra code. A component, unlike a class, derives from the System.ComponentModel.Component class. It also contains a Component Designer generated code region.

The extra code contained in a component declaration enables you to build components by using the Visual Studio .NET Designer interface. You can drag and drop other components from the Toolbox or Server Explorer window onto your component. For example, if you want to add a database connection to your component, you can drag and drop the connection from the Toolbox (see Figure 20.1).

Using the Designer interface with a component.

Figure 20.1. Using the Designer interface with a component.

You can also add a component to the Toolbox, but you can’t add a class to the Toolbox. If you want to create a component that you want to easily use in multiple pages, you’ll need to create a component rather than a class.

Creating a Simple Component

Let’s start by creating a simple component that converts inches to millimeters and millimeters to inches. This component will have two methods, ConvertToMillimeters() and ConvertToInches(), respectively.

Note

When you create a component in VB.NET, any public functions or subroutines that you declare in the component are exposed as methods. Consequently, to create your component to convert inches and millimeters, you need to create a component that contains two public functions. In C#, you can just create the methods directly.

To do so, perform the following steps:

Procedure 20.1. C# Steps

  1. Select Add Component from the Project menu. Name the component Converter.cs and click Open.

  2. Select Code from the View menu.

  3. Add the following code to the body of the component (do not remove the section labeled Component Designer generated code):

    public decimal ConvertToMillimeters(Decimal Inches)
    {
      return Inches * 25.4m;
    }
    
    public decimal ConvertToInches(Decimal Millimeters)
    {
      return Millimeters * 0.03937m;
    }
    

Procedure 20.2. VB.NET Steps

  1. Select Add Component from the Project menu. Name the component Converter.vb and click Open.

  2. Select Code from the View menu.

  3. Add the following code to the body of the component (do not remove the section labeled Component Designer generated code):

    Function ConvertToMillimeters(ByVal Inches As Decimal) As Decimal
        Return Inches * 25.4
    End Function
    
    Function ConvertToInches(ByVal Millimeters As Decimal) As Decimal
        Return Millimeters * 0.03937
    End Function
    

Next, we want to test our component in a Web Form Page. We’ll create a page that contains a form for converting millimeters to inches.

  1. Add a new Web Form Page to your project named TestConverter.aspx.

  2. Add Label, TextBox, and Button controls to the TestConverter.aspx page.

  3. Double-click the Button control (this will switch you to the Code Editor).

  4. Enter the following code for the Button1_Click handler:

    C#

    private void Button1_Click(object sender, System.EventArgs e)
    {
      Converter objConverter = new Converter();
      Label1.Text = objConverter.ConvertToInches( Decimal.Parse(TextBox1.Text)).ToString();
    }
    

    VB.NET

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    VB.NET Handles Button1.Click
      Dim objConverter As Converter
    
      objConverter = New Converter()
      Label1.Text = objConverter.ConvertToInches(TextBox1.Text)
    End Sub
    
  5. Right-click the TestConverter.aspx page in the Solution Explorer window and select Build and Browse.

After you create the Web Form Page to test the component, you should be able to enter a value in millimeters into the text box, click the Button control, and the value converted to inches should be displayed in the Label control (see Figure 20.2).

Using the Designer interface with a component.

Figure 20.2. Using the Designer interface with a component.

Notice that we need to explicitly declare and create an instance of the component in the Button1_Click subroutine. After we create an instance of the component, we can simply call the component’s ConvertToInches() method to convert the contents of the TextBox control to inches.

You should also notice that IntelliSense works with our new component. When you type the name of an instance of a component followed by a period (for example, objConverter.), a list of all the available methods of the component is displayed in a list box.

Creating Components with Static/Shared Methods

In the previous section, we created a component for converting inches and millimeters. Before we could use the component in the Web Form Page, however, we were required to explicitly declare and instantiate an instance of the component.

There’s an easier way to use a component in your applications. Instead of declaring instance methods, you can declare static methods (called shared methods in VB.NET). You don’t have to instantiate a component before you call its static methods.

Let’s create a simple component with static methods for converting ounces to grams and grams to ounces.

Procedure 20.3. C# Steps:

  1. Create a new component for your project named StaticConverter.cs.

  2. Switch to the Code Editor by selecting Code from the View menu.

  3. Add the following code to the body of the component (do not remove the section labeled Component Designer generated code):

    public static decimal ConvertToOunces(decimal grams)
    {
      return grams * 0.0353m;
    }
    
    public static decimal ConvertToGrams(decimal ounces)
    {
      return ounces * 28.35m;
    }
    

Procedure 20.4. VB.NET Steps

  1. Create a new component for your project named SharedConverter.vb.

  2. Switch to the Code Editor by selecting Code from the View menu.

  3. Add the following code to the body of the component (do not remove the section labeled Component Designer generated code):

    Shared Function ConvertToOunces(ByVal grams As Decimal) As Decimal
      Return grams * 0.0353
    End Function
    
    Shared Function ConvertToGrams(ByVal ounces As Decimal) As Decimal
      Return ounces * 28.35
    End Function
    

Notice that both the ConvertToOunces() and ConvertToGrams() methods are declared as static (shared) methods. The method declarations include the keyword Static or Shared. Because of the way these methods are declared, we can access the methods from a Web Form Page without creating an instance of the component.

Next, we need to create a Web Form Page to test our component.

Procedure 20.5. C# Steps

  1. Create a new Web Form Page named TestStaticConverter.aspx.

  2. Add Label, TextBox, and Button controls to the page.

  3. Double-click the Button control (this will switch you to the Code Editor).

  4. Enter the following code for the Button1_Click subroutine:

    private void Button1_Click(object sender, System.EventArgs e)
    {
      Label1.Text =
        StaticConverter.ConvertToGrams(Decimal.Parse(TextBox1.Text)).ToString();
    }
    
  5. Right-click the TestStaticConverter.aspx page in the Solution Explorer window and select Build and Browse.

Procedure 20.6. VB.NET Steps

  1. Create a new Web Form Page named TestSharedConverter.aspx.

  2. Add Label, TextBox, and Button controls to the page.

  3. Double-click the Button control (this will switch you to the Code Editor)

  4. Enter the following code for the Button1_Click subroutine:

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    VB.NET Steps Handles Button1.Click
      Label1.Text = SharedConverter.ConvertToGrams(TextBox1.Text)
    End Sub
    
  5. Right-click the TestSharedConverter.aspx page in the Solution Explorer window and select Build and Browse.

You’ll notice that we did not explicitly declare the StaticConverter or SharedConverter component in the Web Form Page. Because the ConvertToGrams() method is a static method, we can call the method directly.

After reading this section, you might conclude that it makes sense to create every method as a static (shared) method. However, this type of method has an important limitation—you cannot refer to an instance method or property from a static (shared) method. Consequently, if your component needs to maintain state by using an instance property, you cannot take advantage of static (shared) methods.

Adding Properties to a Component

As you’ve seen in previous sections, any public function or public subroutine declared in a component is exposed as a method of the component. So far, we’ve discussed how you can add methods to a component, but we have not discussed properties.

You can add properties to a component in two ways—by declaring a public variable or by using property accessor functions. Because using property accessor functions is the preferred method, we’ll use that method here.

We’ll create a component with a single property and a single method. The property, named Language, will accept a string that represents a language such as French or Indonesian. The SayHello() method will return the string Hello in the language specified.

Procedure 20.7. C# Steps

  1. Create a new component for your project named Hello.cs.

  2. Switch to the Code Editor by selecting Code from the View menu.

  3. Add the following code to the body of the component (do not remove the section labeled Component Designer generated code):

    string _language;
    
    public string Language
    {
      get
      {
        return _language;
      }
      set
      {
        _language = value;
      }
    }
    
    public string SayHello()
    {
      switch ( _language.ToLower() )
      {
        default:
          return "Hello";
        case "spanish":
          return "Hola";
        case "french":
          return "Bonjour";
        case "indonesian":
          return "Selamat";
      }
    }
    

Procedure 20.8. VB.NET Steps

  1. Create a new component for your project named Hello.vb.

  2. Switch to the Code Editor by selecting Code from the View menu.

  3. Add the following code to the body of the component (do not remove the section labeled Component Designer generated code):

    Dim _language As String
    
    Public Property Language() As String
      Get
        Return _language
      End Get
      Set(ByVal Value As String)
       __language = Value
      End Set
    End Property
    
    Function SayHello() As String
      Select Case _language.ToLower
        Case "english"
          Return "Hello"
        Case "spanish"
          Return "Hola"
        Case "french"
          Return "Bonjour"
        Case "indonesian"
          Return "Selamat"
        End Select
    End Function
    

The property is declared in this component by using property accessor functions. The Language property contains a Get() method and a Set() method. When you assign a value to the Language property, the Set() method is called. When you read a value from the Language property, the Get() method is called.

Notice that we use a private variable, named _language, with the Language property. Internal to our component, we use the _language property instead of the Language property.

To test our component, we need to create a new Web Form Page:

  1. Create a new Web Form Page named TestHello.aspx.

  2. Add Label, TextBox, and Button controls to the TestHello.aspx page.

  3. Double-click the Button control (this will switch you to the Code Editor).

  4. Enter the following code for the Button1_Click handler:

    C#

    private void Button1_Click(object sender, System.EventArgs e)
    {
      Hello objHello = new Hello();
      objHello.Language = TextBox1.Text;
      Label1.Text = objHello.SayHello();
    }
    

    VB.NET

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    VB.NET Handles Button1.Click
      Dim objHello As Hello
    
      objHello = New Hello()
      objHello.Language = TextBox1.Text
      Label1.Text = objHello.SayHello()
    End Sub
    
  5. Right-click the TestHello.aspx page in the Solution Explorer window and select Build and Browse.

If you enter the text French into the text box and click the button, the text Bonjour should appear in the Label control (see Figure 20.3).

Adding properties to a component.

Figure 20.3. Adding properties to a component.

Creating a Database Component

Because you can take full advantage of the Visual Designer when building a component, you easily add all of your database logic to a component. In this section, we’ll create a simple database component that retrieves all the records from the Products database table.

Procedure 20.9. C# Steps

  1. Create a component named Products.cs.

  2. Drag the Products database table from under the Northwind data connection onto the Designer surface. Doing this will add both an SqlConnection and SqlDataAdapter to the component.

  3. Add an Untyped DataSet to the component.

  4. Switch to the Code Editor by selecting Code from the View menu.

  5. Enter the following method in the body of the component:

    public DataSet GetProducts()
    {
      sqlDataAdapter1.Fill(dataSet1);
      return dataSet1;
    }
    
  6. Add the following two statements to the top of the component:

    using System.Data;
    using System.Data.SqlClient;
    

Procedure 20.10. VB.NET Steps

  1. Create a component named Products.vb.

  2. Drag the Products database table from under the Northwind data connection onto the Designer surface. Doing this will add both an SqlConnection and SqlDataAdapter to the component.

  3. Add an Untyped DataSet to the component.

  4. Switch to the Code Editor by selecting Code from the View menu.

  5. Enter the following function in the body of the component:

    Function GetProducts() As DataSet
      SqlDataAdapter1.Fill(DataSet1)
      Return DataSet1
    End Function
    

That was easy, wasn’t it? We only need two statements to return a DataSet.

Next, we’ll create a test page that grabs the data from the Products component and displays the data in a DataGrid.

  1. Create a new page named TestProducts.aspx.

  2. Add a DataGrid to the page.

  3. Switch to the Code Editor by selecting Code from the View menu.

  4. Enter the following code for the Page_Load handler:

    C#

    private void Page_Load(object sender, System.EventArgs e)
    {
      Products objProducts = new Products();
      DataGrid1.DataSource = objProducts.GetProducts();
      DataGrid1.DataBind();
    }
    

    VB.NET

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
    VB.NET MyBase.Load
      Dim objProducts As New Products()
    
      DataGrid1.DataSource = objProducts.GetProducts()
      DataGrid1.DataBind()
    End Sub
    
  5. Right-click the TestProducts.aspx page in the Solution Explorer window and select Build and Browse.

Notice that the TestProducts.aspx page does not include any database components such as a DataSet or SqlConnection. All the database components are hidden away in the Products component.

Using DataReaders with Components

In the previous section, we created a database component that returned database records with a DataSet. However, you should be aware that retrieving records with a DataAdapter and DataSet is significantly slower, in almost all situations, than retrieving the same records with a DataReader. In this section, we’ll take a look at how we can modify our database component to use a DataReader instead of a DataSet.

Note

Using a DataReader can be two to three times faster than using a DataSet (depending on the number of rows being requested from the database). To learn more about the speed differences between a DataReader and a DataSet, see the “Performance Comparison: Data Access Techniques” article posted at the msdn.microsoft.com Web site at http://msdn.microsoft.com/library/en-us/dnbda/html/bdadotnetarch031.asp.

Procedure 20.11. C# Steps

  1. Create a new component named ProductsDR.cs.

  2. Drag the Data Connection to the Northwind database from the Server Explorer window onto the Designer surface.

  3. Add an SqlCommand object to the page.

  4. In the Properties window, double-click next to the Connection property to assign the Northwind database connection to the SqlCommand object.

  5. Assign the following SQL SELECT command to the SqlCommand object’s CommandText property:

    SELECT * FROM Products
    
  6. Switch to the Code Editor by selecting Code from the View menu.

  7. Enter the following method in the body of the component:

    public SqlDataReader GetProducts()
    {
      sqlConnection1.Open();
      return sqlCommand1.ExecuteReader(CommandBehavior.CloseConnection);
    }
    
  8. Add the following two statements to the top of the component:

    using System.Data;
    using System.Data.SqlClient;
    

Procedure 20.12. VB.NET Steps

  1. Create a new component named ProductsDR.vb.

  2. Drag the Data Connection to the Northwind database from the Server Explorer window onto the Designer surface.

  3. Add an SqlCommand object to the page.

  4. In the Properties window, double-click next to the Connection property to assign the Northwind database connection to the SqlCommand object.

  5. Assign the following SQL SELECT command to the SqlCommand object’s CommandText property:

    SELECT * FROM Products
    
  6. Switch to the Code Editor by selecting Code from the View menu.

  7. Enter the following method in the body of the component:

    Public Function GetProducts() As SqlDataReader
      SqlConnection1.Open()
      Return SqlCommand1.ExecuteReader(CommandBehavior.CloseConnection)
    End Function
    
  8. Add the following statement to the top of the component:

    Imports System.Data.SqlClient
    

We can bind the data returned from the ProductsDR component to a DataGrid in exactly the same way as we bound the data returned by the Products component in the previous section. However, the data is retrieved much faster with a DataReader than a DataSet.

Notice that when we call the ExecuteReader() method, we pass the special parameter CommandBehavior.CloseConnection. This parameter causes the database connection being used by the DataReader to close automatically after all the records are retrieved by the DataReader. If we did not include this parameter, the database connection would never be explicitly closed.

Creating Multi-Tiered Applications

As an application grows more complex, you’ll need to divide it into multiple tiers. The traditional method of doing this is to use the three-tiered application model. According to this model, an application should be divided into the following tiers:

  • Presentation Tier—Contains the user interface for the application

  • Business Tier—Contains the business rules for the application

  • Data Tier—Contains the data access components for the application

In an ASP.NET application, you use Web Form Pages for the presentation tier. The business and data tiers are typically implemented with business components.

In this section, we’ll create a simple three-tiered application by creating separate components for the business and data tiers. We’ll create a simple order entry application.

We’ll work our way up the tiers starting from the data tier. For the data tier, we’ll create a component that writes orders to the file system. To create the data component, do the following:

Procedure 20.13. C# Steps

  1. Create a new component named DataCom.cs.

  2. Switch to the Code Editor by selecting Code from the View menu.

  3. Add the following code to the body of the component (do not remove the section labeled Component Designer generated code):

    public static void SaveOrder(string OrderID, decimal OrderAmount)
    {
      System.IO.TextWriter objWriter;
    
      objWriter = System.IO.File.AppendText("c:\Orders.txt");
      objWriter.WriteLine("OrderID: " + OrderID);
      objWriter.WriteLine("OrderAmount:" + OrderAmount.ToString());
    
      objWriter.Close();
    }
    

Procedure 20.14. VB.NET Steps

  1. Create a new component named DataCom.vb.

  2. Switch to the Code Editor by selecting Code from the View menu.

  3. Add the following code to the body of the component (do not remove the section labeled Component Designer generated code):

    Public Shared Sub SaveOrder(ByVal OrderID As String, ByVal OrderAmount As Decimal)
      Dim objWriter As System.IO.TextWriter
    
      objWriter = System.IO.File.AppendText("c:Orders.txt")
      With objWriter
        .WriteLine("OrderID: " & OrderID)
        .WriteLine("OrderAmount:" & OrderAmount)
      End With
      objWriter.Close()
    End Sub
    

The DataCom component has a single method, named SaveOrder, that saves an order ID and order amount to a file named Orders.txt located at the root of the C: drive.

Next, we’ll create the business tier by creating a single business component. The business component will implement the business rule that you cannot enter an order for an amount less than $1.00 or an order greater than $500.00.

Procedure 20.15. C# Steps

  1. Create a new component for your project named BizCom.cs.

  2. Switch to the Code Editor by selecting Code from the View menu.

  3. Add the following code to the body of the component (do not remove the section labeled Component Designer generated code):

    public static bool AddOrder(string OrderID,decimal OrderAmount)
    {
      if (OrderAmount > 1 && OrderAmount < 500)
      {
        DataCom.SaveOrder(OrderID, OrderAmount);
        return true;
      }
      else
        return false;
    }
    

Procedure 20.16. VB.NET Steps

  1. Create a new component for your project named BizCom.vb.

  2. Switch to the Code Editor by selecting Code from the View menu.

  3. Add the following code to the body of the component (do not remove the section labeled Component Designer generated code):

    Public Shared Function AddOrder(ByVal OrderID As String, ByVal OrderAmount As Decimal) As
    VB.NET Steps Boolean
      If OrderAmount > 1 And OrderAmount < 500 Then
        DataCom.SaveOrder(OrderID, OrderAmount)
        Return True
      Else
        Return False
      End If
    End Function
    

The BizCom class checks whether the OrderAmount is greater than 1 and less than 500. If the order passes the check, the BizCom component calls the DataCom component to save the order.

Finally, we need to create the presentation tier. We’ll create the presentation tier by creating a Web Form Page named Presentation.aspx:

  1. Add a new Web Form Page to your project named Presentation.aspx.

  2. Add an HTML Label with the text Order ID.

  3. Add a TextBox control.

  4. Add a second HTML Label with the text Order Amount.

  5. Add a second TextBox control.

  6. Add a Web Forms Label control.

  7. Add a Web Forms Button control.

  8. Add a Button1_Click handler by double-clicking the Button control (this will switch you to the Code Editor).

  9. Enter the following code for the Button1_Click handler:

    C#

    private void Button1_Click(object sender, System.EventArgs e)
    {
      if (BizCom.AddOrder(TextBox1.Text, Decimal.Parse(TextBox2.Text)) )
      {
        Label1.Text = "Order Added!";
        TextBox1.Text = "";
        TextBox2.Text = "";
      }
      else
        Label1.Text = "Could Not Add Order!";
    }
    

    VB.NET

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    VB.NET Handles Button1.Click
      If BizCom.AddOrder(TextBox1.Text, TextBox2.Text) Then
        Label1.Text = "Order Added!"
        TextBox1.Text = ""
        TextBox2.Text = ""
      Else
        Label1.Text = "Could Not Add Order!"
      End If
    End Sub
    
  10. Right-click the Presentation.aspx page in the Solution Explorer window and select Build and Browse.

If you enter a value between 1 and 500 into the Order Amount text box, and submit the form, a new order is added to the Order.txt file. If you do not enter a valid order amount, the error message “Could Not Add Order!” is displayed (see Figure 20.4).

A simple multi-tiered application.

Figure 20.4. A simple multi-tiered application.

Note

You must supply the ASPNET account with permissions to write to the hard drive to write to the Orders.txt file:

  1. Right-click the C: drive.

  2. Select the Security Tab.

  3. Grant Write permissions to either the ASPNET or Guest account.

Creating a Library of Components

To get the most out of using components, you’ll want to reuse the same components in multiple projects. In other words, you’ll want to develop a standard library of components that you can use in your projects.

When you add a component (or a class) to your project, the component is compiled into the same assembly as the rest of your project. For example, if you are working on a project named myWebApp, the component is compiled into the myWebApp.dll assembly when you compile the project.

Note

An assembly is the actual file (or files) on your hard drive that contains the application logic for your project. When you compile a project by selecting Build and Browse, the project is compiled into an assembly.

If you want to use the same component in multiple projects, you’ll need to compile the component into an independent assembly. You can create a component that is independent from any particular Web Application project by creating a Class Library project. A single class library can contain multiple components.

To do so, perform the following steps:

Procedure 20.17. C# Steps

  1. Open the File menu, and select New, Project.

  2. Select the Visual C# Projects folder and select the Class Library template. Name the project MyLibrary and click OK.

  3. Delete the Class1.cs file from the MyLibrary project by right-clicking the Class1.cs file in the Solution Explorer window and selecting Delete.

  4. Add a new component to the MyLibrary project named GeneralHello.cs.

  5. Enter the following code for the GeneralHello component (do not modify the section labeled Component Designer generated code):

    public string SayHello()
    {
      return "Hello!";
    }
    
  6. Compile the component by selecting Build MyLibrary from the Build menu.

Procedure 20.18. VB.NET Steps

  1. Open the File menu, and select New, Project.

  2. Select the Visual Basic Projects folder and select the Class Library template (see Figure 20.5). Name the project MyLibrary and click OK.

    Creating a Class Library project.

    Figure 20.5. Creating a Class Library project.

  3. Delete the Class1.vb file from the MyLibrary project by right-clicking the Class1.vb file in the Solution Explorer window and selecting Delete.

  4. Add a new component to the MyLibrary project named GeneralHello.vb.

  5. Enter the following code for the GeneralHello component (do not modify the section labeled Component Designer generated code):

    Public Function SayHello() As String
      Return "Hello!"
    End Function
    
  6. Compile the component by selecting Build MyLibrary from the Build menu.

After completing these steps, you’ll have a new component named GeneralHello. The component has one method—SayHello()—that simply returns the string Hello!.

The component is stored in an assembly on your hard drive named MyLibrary.dll. If you want to use the GeneralHello component in another project, you need to add a reference to this assembly to the project:

  1. Create a new ASP.NET Web Application project named MyProject by selecting New Project from the File menu.

  2. Add a reference to the GeneralHello assembly by selecting Add Reference from the Project menu. Select the Projects tab and click the Browse button. Browse to the MyLibrary.dll assembly and click Open (see Figure 20.6). The MyLibrary.dll assembly will be located at the following path:

    Adding a reference to an assembly.

    Figure 20.6. Adding a reference to an assembly.

    My DocumentsVisual Studio ProjectsMyLibraryinDebug
    
  3. Add a new Web Form Page to the project named TestGeneralHello.aspx.

  4. Add a Label control to the TestGeneralHello.aspx page.

  5. Switch to the Code Editor by selecting Code from the View menu.

  6. Enter the following code for the Page_Load handler:

    C#

    private void Page_Load(object sender, System.EventArgs e)
    {
      Label1.Text = MyLibrary.GeneralHello.SayHello();
    }
    

    VB.NET

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
    VB.NET MyBase.Load
      Label1.Text = myLibrary.GeneralHello.SayHello
    End Sub
    
  7. Right-click the TestGeneralHello.aspx page and select Build and Browse.

The TestGeneralHello.aspx page uses the GeneralHello component to display the text Hello! in a Label control. You can use the GeneralHello component in the TestGeneralHello.aspx page even though the component is not defined in the same project. Because you added a reference to the GeneralHello.dll assembly, the component is available to the project.

This means that if you want to use a class library developed by a friend, your friend would simply need to email you the assembly. All the information about the class library is contained in the assembly.

Note

Any references that you add to a project appear under the References folder in the Solution Explorer window.

Adding Components to the Toolbox

If you create a genuinely useful set of components that you plan to use with multiple projects, you’ll want to add the components to the Toolbox. Do the following to add the components in the MyLibrary project to the Toolbox:

  1. Open the TestGeneralHello.aspx page.

  2. Right-click the Toolbox and select Add Tab. Enter the name MyLibrary for the new tab.

  3. Right-click beneath your new tab on the Toolbox and select Customize Toolbox.

  4. In the Customize Toolbox dialog box, select the .NET Framework Components tab.

  5. Click Browse and navigate to the MyLibrary.dll file on your hard drive. It should be in the following directory:

    My DocumentsVisual Studio ProjectsMyLibraryinDebug
    
  6. Click OK.

After you complete these steps, the GeneralHello component will appear in the Toolbox beneath the MyLibrary tab. If you want to use the GeneralHello component in a page, you can simply drag and drop the component from the Toolbox onto the page. After the component has been added to the page, it will appear in the component bar at the bottom of the Designer window (see Figure 20.7).

Custom component added to the Toolbox.

Figure 20.7. Custom component added to the Toolbox.

When you drag a component onto a page, code for declaring and initializing the component is automatically added to the code-behind class for the page. For example, if you add the GeneralHello component to a page, the following two statements are added:

C#

protected MyLibrary.GeneralHello generalHello1;
this.generalHello1 = new MyLibrary.GeneralHello(this.components);

VB.NET

Protected WithEvents GeneralHello1 As MyLibrary.GeneralHello
Me.GeneralHello1 = New MyLibrary.GeneralHello(Me.components)

The declaration statement is added to the top of the code-behind file for the page and the initialization statement is added to the Web Form Designer generated code region.

Accessing the Current HttpContext in a Component

Within a Web Form Page, you have access to all the information about the current request. You have direct access to objects such as the Request, Response, Session, User, Trace, and Cache objects. Within a component, on the other hand, you must do a little work before you access these objects.

Before you can access the intrinsic ASP.NET objects, you must first retrieve a reference to the current HttpContext. The HttpContext object has properties that expose all the standard ASP.NET intrinsic objects.

For example, suppose that you want to create a database component that caches database data in the server’s memory. Instead of accessing the database with each database query, the component will check the cache first. To create this component, you’ll need some way of referring to the Cache object. You can get to the Cache object by getting a reference to the current HttpContext.

Perform the following steps to create the CachedData component:

Procedure 20.19. C# Steps

  1. Create a new component named CachedData.cs.

  2. Drag the Products table from under the Northwind Data Connection onto the Designer surface. This will add both an SqlConnection and SqlDataAdapter to the component.

  3. Add an Untyped DataSet to the component.

  4. Switch to the Code Editor by selecting Code from the View menu.

  5. Enter the following method:

    public DataSet GetResults(string CommandText)
    {
      // Get reference to current HttpContext
      HttpContext Context = HttpContext.Current;
    
      // Try to retrieve data from Cache
      dataSet1 = (DataSet)Context.Cache[CommandText.ToLower()];
    
      // If can't, get from database
      if (dataSet1 == null)
      {
        Context.Trace.Warn("Retrieving data from DB");
        dataSet1 = new DataSet();
        sqlDataAdapter1.SelectCommand.CommandText = CommandText;
        sqlDataAdapter1.Fill(dataSet1);
        Context.Cache[CommandText.ToLower()] = dataSet1;
      }
      else
        Context.Trace.Warn("Retrieving data from memory");
        // In either case, return the DataSet
        return dataSet1;
    }
    
  6. Add the following statements to the top of the component:

    using System.Web;
    using System.Data;
    using System.Data.SqlClient;
    

Procedure 20.20. VB.NET Steps

  1. Create a new component named Cacheddata.vb.

  2. Drag the Products table from under the Northwind Data Connection onto the Designer surface. This will add both an SqlConnection and SqlDataAdapter to the component.

  3. Add an Untyped DataSet to the component.

  4. Switch to the Code Editor by selecting Code from the View menu.

  5. Enter the following method:

    Function GetResults(ByVal CommandText As String) As DataSet
      ' Get reference to current HttpContext
      Dim Context As HttpContext = HttpContext.Current
    
      ' Try to retrieve data from Cache
      DataSet1 = Context.Cache(CommandText.ToLower())
    
      ' If can't, get from database
      If (DataSet1 Is Nothing) Then
        Context.Trace.Warn("Retrieving data from DB")
        DataSet1 = New DataSet()
        SqlDataAdapter1.SelectCommand.CommandText = CommandText
        SqlDataAdapter1.Fill(DataSet1)
        Context.Cache(CommandText.ToLower()) = DataSet1
      Else
        Context.Trace.Warn("Retrieving data from memory")
      End If
    
      ' In either case, return the DataSet
      Return DataSet1
    End Function
    

The first line in the GetResults() method returns a reference to the current HttpContext. Notice that after the reference is retrieved, both the Cache and Trace objects can be used.

The CachedData component first attempts to retrieve a DataSet representing the results of an SQL query from the cache. If the results are not present in the cache, the component retrieves the results from the database and adds the results to the cache. In either case, the results are returned.

You can test the component by building the following page:

  1. Add a page to your project named TestCachedData.aspx.

  2. Select Document in the Properties window and assign the value FlowLayout to the pageLayout property and the value True to the Trace property.

  3. Add a TextBox, Web Forms Button, Web Forms Label control, and DataGrid to the page.

  4. Double-click the Button control to add a Button1_Click handler and switch to the Code Editor.

  5. Enter the following code for the Button1_Click handler:

    C#

    private void Button1_Click(object sender, System.EventArgs e)
    {
      CachedData objCachedData = new CachedData();
      DataGrid1.DataSource = objCachedData.GetResults(TextBox1.Text);
      DataGrid1.DataBind();
    }
    

    VB.NET

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    VB.NET Handles Button1.Click
      Dim objCachedData As New CachedData()
      DataGrid1.DataSource = objCachedData.GetResults(TextBox1.Text)
      DataGrid1.DataBind()
    End Sub
    
  6. Right-click TestCachedData.aspx in the Solution Explorer window and select Build and Browse.

When the page opens, you can type any SELECT statement into the text box and click the button to see the results in the DataGrid (see Figure 20.8). For example

Testing the CachedData component.

Figure 20.8. Testing the CachedData component.

SELECT * FROM Categories

When you execute the SELECT statement for the first time, the results are retrieved from the database. Subsequently, the results are retrieved from the cache. You can verify this by looking at the Trace Information section.

Summary

In this chapter, you learned how to create both C# and VB.NET business components. First, you learned how to create simple business components by adding methods and properties to a component. You also learned how to create a simple business component that retrieves database data.

Next, we looked at how you can use components to divide an application into multiple tiers. We created a simple multi-tier application by creating components for the business and data tiers.

We then examined how you can package a library of components in a separate assembly. You learned how to create a separate Class Library project and refer to the class library in an ASP.NET Web Application project. You also learned how you can add components to the Toolbox.

Finally, we discussed the importance of the HttpContext object. You learned how to use the HttpContext object to refer to ASP.NET intrinsics, such as the Cache and Trace objects within a component.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset