|
 |
|
|
 |
 |
 |
 |
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.
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
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.
Properties
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.
Conclusion
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).
|
|
|
|
|
|