MSDN Magazine > Issues and Downloads > 2001 > January >  Visual Programmer: Advanced ASP.NET Server-side...
Advanced ASP.NET Server-side Controls
George Shepherd
n my October 2000 column I looked at the motivation for the new Active Server Pages.NET (ASP.NET) server-side controls and their basic structure. In this month's column I'll take a closer look at ASP.NET and a deeper look at ASP.NET server-side controls, including control state management, round-trips and posting data, and developing a richer UI using both compositional and noncompositional controls.
      During the mid-90s, you could create rich, active Web sites by trying to extend the browserâ€"primarily through ActiveX® controls or Java-language applets. Unfortunately this approach presented several problems, the most limiting being that not every client site supported these technologies. This is especially true now with the rapid proliferation of next-generation devices. No longer can you count on one or two well-known client environmentsâ€"the client to your Web site may be any of a huge number of potential devices, ranging from small handheld devices or cell phones to full-blown desktop computers. The Microsoft® .NET Framework solves this problem by having the server generate the user interface code as pure HTML (as well as newer standards like WML and XHTML) and then squirting the HTML out to the browser. Because every browser understands HTML, that's a reasonable way to get UI presentation out to the client. At the heart of the .NET platform is ASP.NET.


      Of course, generating raw UI from the server is basically how ASP works now. An ASP page generates HTML dynamically based upon various runtime factors on the server side. ASP has an internal object model that's accessible as a set of IDispatch pointers. To get some HTML out to the client, you just grab the ASP Response object (available through an object's context) and call IResponse::Write. The string you hand to the Write method is the one that shows up at the client's browser.
      While ASP is an effective and widely used means of creating Web sites, it suffers from several downsides. First, ASP is somewhat disorganized. Almost anything can go on an ASP page, including raw HTML, scripting code, COM objects, and text. This means that there's no formal distinction between the content of a page and its behavior. It's almost as if you're back to the old days of spaghetti coding principlesâ€"just smear some code on the page and see what happens. ASP.NET imposes some order over the standard ASP programming model.
      The second downside of traditional ASP is that you end up using typeless scripting languages such as VBScript and JScript. You can install other scripting engines that impose type-checking, however, they're usually not as well-known and as widely-used as VBScript and JScript®. ASP.NET clearly separates the script-based portion of a Web page from its contents.
      The final downside of plain vanilla ASP is that to get anything to happen on a Web page, you have to write a lot of code. If you're an old-time Windows®-based developer, you know that the declarative programming model is a much better model. (Think of designing a dialog box by hand versus using the resource editor.) ASP.NET brings the declarative model to Web programming. The ASP.NET server-side controls work on a Web page by simply declaring them. As the ASP.NET page loads, it instantiates the controls listed within the ASP page. Then it becomes the control's job to emit some HTML that the browser can understand.

Composing from other Controls

      This month I'll use a simple Fahrenheit/Centigrade conversion control as an example of a compositional control, or a server-side control composed of other standard controls (like listboxes and radio buttons). ASP.NET will include a number of lightweight controls like this to make your life easier. In my control, the temperature converter control gathers together two textboxes and two push buttons into a single component. Type a number into the Fahrenheit box, click on the Fahrenheit To Centigrade button, and the control converts Fahrenheit temperatures to Centigrade temperatures. Type a number into the Centigrade box, click on the Centigrade To Fahrenheit button, and the control converts Centigrade temperatures to Fahrenheit temperatures. Figure 1 shows the control in action within Microsoft Internet Explorer 5.5.

Figure 1 Temperature Converter Control Dialog
Figure 1 Temperature Converter Control Dialog

      The temperature converter control is written in C# (though it could just have easily been written in Visual Basic). Figure 2 contains the code for the entire control. The next few sections are a tour of the code, highlighting important aspects including how to maintain properties in a control and how to respond to the child controls within the main control.


      The idea behind a control is usually to provide a user interface for managing a small piece of data, normally represented as a property within the control. This control maintains two propertiesâ€"the actual Fahrenheit temperature and the Centigrade temperatureâ€"represented as doubles. C# promotes using accessor and mutator functions for managing a control's properties. Rather than simply listing a member variable as a type, like this:
Double m_fFahrenheitValue;
Double m_fCentigradeValue;
C# provides a useful syntax, letting you hook functionality into the process of assigning and retrieving values. For example, the code in Figure 3 shows the C# syntax for managing a property through accessor and mutator functions.
      The temperature control's Fahrenheit and Centigrade properties are accessed through get and set functions. The C# syntax shown in Figure 3 causes the accessor functions (the get functions) to be called when values are requested from the control's FahrenheitValue and CentigradeValue. Notice that this control simply gets the actual Fahrenheit value from the textbox that represents that value. Similarly, the mutator function (the set function) is called when values are assigned to the control's FahrenheitValue and CentigradeValue, storing the new values in the textbox representing the value. This makes managing the temperature values very straightforward.

Child Controls

      The server-side control I described in my October 2000 column didn't do muchâ€"it just squirted a single line of HTML out to the browser. To make a control with any functionality at all usually means composing a control from other elements (such as other standard controls). The ASP.NET server-side control framework provides this functionality in two ways. You may either compose a control from separate subcontrols by creating them at page load-time or you can have the ASP.NET page render the controls out as HTML. Now let's look at composing server-side controls by creating child controls at runtime.
      When an ASP page includes a server-side control, the ASP framework calls the control's CreateChildControls method. CreateChildControls is an overrideable function whose purpose is to create child controls on the form. For example, the temperature converter control in Figure 2 creates two LiteralControls, two TextBox controls, and two button controlsâ€"these Web controls come from the System.Web.UI namespace.
      Notice the code in Figure 2 creates two LiteralControls (the Fahrenheit and Centigrade labels), but does not hold on to them. That's OK because I don't plan to change the text in the LiteralControl, so it's not necessary to hold on to member variables representing the labels. However, notice that the TextBoxes representing the actual temperature values are member variables within the TemperatureConverter class. The TemperatureConverter control holds on to the TextBoxes as variables so the values stored by the control are the latest values typed in by the user.
      Also notice that each child control is added to the TemperatureControl's list of child controls (the name of the collection is Controls) through the function named Controls.Add. The main control holds the child controls and the server-side control takes responsibility for running through the collection of child controls and rendering them out to the client using HTML.

Responding to Button Presses

      So far, adding state to the control and having the main control create child controls gets you pretty far. If you request an ASP.NET page using this control, you'll see pretty much the same thing as the dialog in Figure 1. However, when the user presses one of the conversion buttons, you want the control to respond by performing the requested version. So you need to tack handlers onto the push buttons.
      As each button is added to the ASP.NET form, those event handlers are attached to the button using the button's AddOnClick method (this is subject to change in future beta versions). AddOnClick requires a single parameter: an EventHandler delegate (which comes from the System namespace). For example, the Fahrenheit To Centigrade button updates the current Centigrade value to reflect the current Fahrenheit value. When someone pushes the Fahrenheit To Centigrade button, some code has to execute. In the temperature converter example, the Fahrenheit To Centigrade button is attached to an EventHandler delegate, which in turn has been wired to the handler for the button. The job of the handler is to simply convert the temperature from one scale to the other. Here's the handler for converting from Fahrenheit to Centigrade:
private void F2CConvertBtn_Click(
  Object sender, EventArgs e) {
    CentigradeValue = F2C(FahrenheitValue);
      When you convert from Fahrenheit to Centigrade, simply accessing the FahrenheitValue property within the call to F2C gets the data out of the Fahrenheit textbox. Assigning a value to the CentigradeValue property puts the Centigrade property value into the Centigrade textbox.

Using the Control on the Page

      Once the control is compiled into an assembly, you can use it within ASP.NET. Figure 4 shows some ASP.NET code that declares an instance of the temperature converter. When the ASP.NET framework loads this page, ASP.NET writes out the body, center, and font tags. Then the form tag manages the input controls that will be emitted by the server-side control. For the complete picture, look at the HTML emitted by the server-side control (see Figure 5).

HTML Produced by the Server-side Control

      The basic job of an ASP.NET server-side control is to emit some markup language that the browser can deal with. Notice in Figure 5 that in the place of the server-side control declaration are two labels, two edit controls with numerical values in them, and two push buttons to submit data entered on the form to the server. The beauty of the server-side control architecture is that you don't have to code up those lines. Anytime you need a temperature converter control, you can just drop in the temperature converter server-side control shown in Figure 2.


      The ASP.NET server-side control architecture promises to dramatically speed up Web site creation and management. It's very similar to when developers went from the old days of having to program everything in a Windows-based application by using C and the SDK to using MFC. MFC introduced a framework over the collective programming details known as the Windows SDK. Rather than having to code every Window class and set up every WndProc by hand to get an application working, MFC does a lot of the preliminary work for you. In the same way, rather than having to write out every little line of HTML to make a Web page work, you can collapse functionality into an ASP.NET server-side control and then simply use them wherever you need to. This month I looked at creating a server-side control composed of child controls. In a subsequent column I'll look at writing a noncompositional server-side controlâ€"or one that manages child controls by rendering them out to the client as HTML.
George Shepherd is an Associate Director at Plural where he helps companies use Microsoft technologies effectively. In addition, George delivers seminars with DevelopMentor and is the coauthor of Programming Visual C++ (Microsoft Press, 1998) and MFC Internals (Addison-Wesley, 1996).

From the January 2001 issue of MSDN Magazine

Page view tracker