Developing Microsoft ASP.NET Server Controls and Components

Overview

Web Forms—the Page and Control Framework at the heart of ASP.NET—makes it easier to develop dynamic Web applications. But you can go beyond the controls that ship with ASP.NET—and power up your Web sites and applications—by creating your own server controls. You can also develop and distribute your own controls for commercial use. This comprehensive guide, direct from key insiders who really know the technology, combines conceptual and architectural details with practical, how-to information and real-world code ...

See more details below
Available through our Marketplace sellers.
Other sellers (Paperback)
  • All (25) from $1.99   
  • New (2) from $58.12   
  • Used (23) from $1.99   
Close
Sort by
Page 1 of 1
Showing All
Note: Marketplace items are not eligible for any BN.com coupons and promotions
$58.12
Seller since 2009

Feedback rating:

(802)

Condition:

New — never opened or used in original packaging.

Like New — packaging may have been opened. A "Like New" item is suitable to give as a gift.

Very Good — may have minor signs of wear on packaging but item works perfectly and has no damage.

Good — item is in good condition but packaging may have signs of shelf wear/aging or torn packaging. All specific defects should be noted in the Comments section associated with each item.

Acceptable — item is in working order but may show signs of wear such as scratches or torn packaging. All specific defects should be noted in the Comments section associated with each item.

Used — An item that has been opened and may show signs of wear. All specific defects should be noted in the Comments section associated with each item.

Refurbished — A used item that has been renewed or updated and verified to be in proper working condition. Not necessarily completed by the original manufacturer.

New
0735615829 *BRAND NEW* Ships Same Day or Next!

Ships from: Springfield, VA

Usually ships in 1-2 business days

  • Canadian
  • International
  • Standard, 48 States
  • Standard (AK, HI)
  • Express, 48 States
  • Express (AK, HI)
$126.01
Seller since 2013

Feedback rating:

(0)

Condition: New
10/01/2000 New Shipped from Spain within 10 to 15 days. *****PLEASE NOTE: This item is shipping from an authorized seller in Europe. In the event that a return is necessary, ... you will be able to return your item within the US. To learn more about our European sellers and policies see the BookQuest FAQ section***** Read more Show Less

Ships from: Malaga, Spain

Usually ships in 1-2 business days

  • Canadian
  • International
  • Standard, 48 States
  • Standard (AK, HI)
  • Express, 48 States
  • Express (AK, HI)
Page 1 of 1
Showing All
Close
Sort by
Sending request ...

Overview

Web Forms—the Page and Control Framework at the heart of ASP.NET—makes it easier to develop dynamic Web applications. But you can go beyond the controls that ship with ASP.NET—and power up your Web sites and applications—by creating your own server controls. You can also develop and distribute your own controls for commercial use. This comprehensive guide, direct from key insiders who really know the technology, combines conceptual and architectural details with practical, how-to information and real-world code samples to show exactly how to create custom, reusable, professional-quality server controls with rich design-time functionality. It also provides essential information about configuration and the HTTP runtime, packaging, deployment, debugging, and developing controls that incorporate XML Web services, plus other vital topics. And it introduces the ASP.NET Web Matrix tool for creating Web applications and for using server controls. Topics covered include:

OVERVIEW

  • ASP.NET page programming
  • Component programming

SERVER CONTROLS

  • User controls
  • Implementing properties
  • View state management
  • Rendering
  • Control life cycle
  • Events and Postback
  • Styles
  • Composite, validator, and data-bound controls
  • Client-side behavior
  • Design-time functionality
  • Localization, licensing, and deployment

SERVER COMPONENTS

  • XML Web services
  • HTTP handlers

SERVER CONTROL CASE STUDIES

  • Templated data-bound controls
  • DHTML-based server controls

“[This book] is a must-have for all serious ASP.NET component developers.”

–Scott Guthrie, Product Unit Manager, Microsoft ASP.NET Product Team

Read More Show Less

Editorial Reviews

From Barnes & Noble
The Barnes & Noble Review
Way back when, Microsoft’s COM technology unleashed a huge marketplace for components -- and a torrent of developer creativity. Now Microsoft hopes that ASP.NET server controls and components will have the same impact on web development -- and, judging from the early marketplace reaction, it just might happen. Whether you’re interested in ASP.NET controls purely for your own projects or as a way to market your server-side code to the world, this book is your definitive resource.

The authors bring together expert guidance for every facet of development: architectural guidelines, extensive task-based information, and, of course, plenty of (downloadable) code samples. Their code samples use standards created by ASP.NET’s own development team -- not surprising, given that one of the book’s coauthors served on that team. Follow this book’s approach, and your controls will fit neatly with the built-in controls that ship with ASP.NET.

Early on, the authors introduce both models for implementing ASP.NET server controls, showing how to use (and choose between) declaratively authored user controls and programmatically authored custom controls. Next, they introduce composite and templated controls; controls with client-side behavior; validator and data-bound controls; and practical techniques for localization and licensing.

There’s a full section on integrating web service functionality into an associated server control, including optimization via caching. The authors conclude with a series of detailed case studies, including a data-bound templated control that generates customizable, interactive, columnar data representations, and a DHTML date picker control that encapsulates logic for targeting multiple browsers. Bill Camarda

Bill Camarda is a consultant, writer, and web/multimedia content developer. His 15 books include Special Edition Using Word 2000 and Upgrading & Fixing Networks For Dummies®, Second Edition.

Read More Show Less

Product Details

  • ISBN-13: 9780735615823
  • Publisher: Microsoft Press
  • Publication date: 7/31/2002
  • Series: Pro-Developer Series
  • Pages: 722
  • Product dimensions: 7.38 (w) x 9.00 (h) x 1.53 (d)

Meet the Author

Nikhil Kothari is a developer on the ASP.NET team and has developed many of the complex controls that ship with the .NET Framework SDK.

Read More Show Less

Read an Excerpt

Chapter 5.
Developing a Simple Custom Control
Server Control Overview
A Trivial Server Control Example
Compiling and Deploying a Server Control
Using a Custom Control on a Page
Exposing a Property: The PrimeGenerator Control Example
Deriving from WebControl
Test Page for the PrimeGenerator Control
Choosing the Base Class for Your Control
Applying Design-Time Attributes
Applying TagPrefixAttribute
Custom Controls in Visual Studio .NET
Adding a Custom Control to the Toolbox
Using Custom Controls from the Toolbox
Customizing the Toolbox Icon
Debugging a Server Control
Summary

5 Developing a Simple Custom Control

In Chapter 4, "User Controls: From Page to Control," we described declaratively authored user controls that are deployed as text files (.ascx and optional code- behind files). In this chapter, we will describe controls that are authored in code and deployed in the form of compiled class libraries. To differentiate between the two control authoring models, we will use the term custom control when referring to a control that is authored as a managed class and compiled before deployment.

You can develop custom controls by using any code editor and the .NET Framework SDK. In this chapter, we will describe the essential steps for authoring a custom control and show you how to enable design-time features that give your control a professional look and feel when it is used in a designer such as Visual Studio .NET. We will also show you how to compile a custom control using command-line tools that ship with the .NET Framework SDK. In addition, we’ll describe how to debug a server control using command-line tools and using Visual Studio .NET. Because this chapter focuses on programming, we will not get into the details of authoring a server control in Visual Studio .NET. You can see those details in the topic "Walkthrough: Creating a Web Custom Control" in the .NET Framework SDK or MSDN documentation.

Server Control Overview

An ASP.NET server control is a component that executes program logic on the server, provides a programmable object model, and renders markup text (such as HTML, XML, and WML) to a Web browser client or other viewing device. A server control is a fundamental building block of an ASP.NET Web application. Although a significant amount of plumbing is needed to enable a class to interact with the ASP.NET page framework and to participate in an HTTP request/response scenario, ASP.NET frees you from low-level details by providing a base class (System.Web.UI.Control) that implements the necessary plumbing. To author a server control, you must define a class that directly or indirectly derives from System.Web.UI.Control. All ASP.NET controls that ship with the .NET Framework SDK derive from Control or from one of its derived classes.

Figure 5-1 shows the hierarchy of the base classes for server controls. The full class hierarchy containing all the server controls in ASP.NET is shown in Chapter 2, "Page Programming Model."

Figure 5-1 Hierarchy of the base classes for server controls (Image unavailable)

The Control class provides the basic functionality for participating in the page framework. In particular, it provides the functionality that allows a server control to be placed within the control tree that represents an .aspx page. The Control class also implements the System.ComponentModel.IComponent interface, which makes it a designable component. A designable component can be added to the toolbox of a visual designer, can be dragged onto a design surface, can display its properties in a property browser, and can provide other kinds of design-time support.

The WebControl class adds functionality to the base Control class for rendering HTML content. WebControl provides support for styles through properties such as Font, Height, Width, BackColor, and ForeColor. Later in this chapter, in the "Choosing the Base Class for Your Control" section, we will provide scenario-based guidelines to help you determine the base control class from which you should derive your control.

A Trivial Server Control Example

To demonstrate the mechanics of implementing a control, we’ll start by creating a very simple server control that merely renders a text string to the client. Our control derives from the base Control class to participate in the HTTP request/response processing provided by the page framework and overrides the inherited Render method to write to the output text stream. Listing 5-1 shows the code for our control.

using System;using System.Web.UI; namespace MSPress.ServerControls { public class SimpleControl : Control { protected override void Render(HtmlTextWriter w riter) { writer.Write("I don’t do anything useful, " ); writer.Write("but at least I’m a control... "); } }}

Listing 5-1 SimpleControl.cs

NOTE:

If you are using Visual Studio .NET, start a new Microsoft Visual C# Control Library project, delete the designer-generated code in WebCustomControl1.cs, and replace it with the code we provide for the control.

System.Web.UI.HtmlTextWriter is a utility class that encapsulates the functionality of writing HTML to a text stream. In Chapter 8, "Rendering," we will show you how to use the methods of the HtmlTextWriter class to simplify HTML rendering. For now, SimpleControl simply passes text into the Write method of the HtmlTextWriter instance. The Write method outputs the specified text to the HTTP response stream and is equivalent to the Response.Write method in traditional Active Server Pages programming. Do not directly invoke Page.Response.Write from your controls because doing so breaks the encapsulation provided by the page framework. Instead, override one of the rendering methods provided by the Control or WebControl class to write to the response stream. We’ll explain the rendering process in greater detail in Chapter 8.

The using declarations enable you to access types by shorter names instead of their fully qualified class names. Thus, Control is equivalent to System.Web.UI.Control. The using declarations do not add any overhead, and they make your code more readable. You must declare your control in a namespace so that page developers can use your control declaratively on pages, as you will soon see.

The Render method, which SimpleControl overrides, corresponds to the Render phase in a control’s life cycle. A control writes text to the underlying HTTP response stream during this phase.

Compiling and Deploying a Server Control

For a custom control to be usable on a page, the control must be compiled into an assembly and made accessible to the ASP.NET runtime. If you are not familiar with the concept of assembly, think of it as a dynamic-link library (DLL) implemented in managed code.

In this book’s sample files, we have provided batch files for building from the command line and provided a Visual Studio .NET solution file (BookCodeCS.sln for C#) for opening the project in Visual Studio .NET. We will discuss the command-line procedure in this section, and we’ll show how to use a custom control in Visual Studio .NET in the section "Custom Controls in Visual Studio .NET."

The batch files in the book’s sample files contain commands that will compile all the control samples in this book. If you want to get a feel for building a server control assembly, follow the instructions in the next paragraph. However, before executing the commands, copy the source files for the control samples in this chapter to a directory other than the one in which you installed the source code so that you don’t overwrite the installed files.

To compile the control shown in Listing 5-1, navigate to the directory that contains the source file for SimpleControl (for example, C:\MyBookCodeCS\MyServerControls) and execute the following command:

csc /t:library /out:MSPress.ServerControls.dll / r:System.dll /r:System.Web.dll SimpleControl.cs

The csc command invokes the C# compiler. The /t option tells the compiler that the target assembly is a library. The /out option provides the name of the output file. The /r option provides the names of the assemblies whose metadata is referenced by the classes being compiled. At this point, we need to reference only two assemblies: System and System.Web. When you execute the compiler command, it will generate a library assembly named MSPress.ServerControls in the file MSPress.ServerControls.dll.

Each ASP.NET application has a special location from which it can access private assemblies. (We’ll explain what private means shortly.) That location is the bin directory immediately under the virtual root representing an Internet Information Services (IIS) Web application. If your Web application’s virtual root is named BookWeb and maps to a path such as C:\BookWebDir, the directory C:\BookWebDir\bin should hold assemblies referenced by pages in the BookWeb Web directory. Binaries that are needed by pages in subdirectories must also be placed in the bin directory directly under the virtual root. For example, the bin directory for pages in C:\BookWebDir\Chapter5 is also C:\BookWebDir\bin. If you ran the setup program included with the book’s sample files, the BookWeb Web application and its bin directory are already created for you.

If you want to follow the instructions in this chapter to understand the mechanics of the process, create an IIS virtual root different from the BookWeb application that was created for you when you installed the samples. If you have not created an IIS virtual root before, see the Introduction of this book for instructions. It is important that you create a new Web application (such as MyBookWeb) so that you don’t overwrite the pages and binaries that are part of the BookWeb application. You must also create a directory named bin under the virtual root.

Next copy the MSPress.ServerControls.dll file that you created earlier to the bin directory of your Web application. Here’s an example:

copy MSPress.ServerControls.dll \bin

The assembly that you created and copied into the application’s bin directory is known as a private assembly because only pages in your Web application can reference it. In Chapter 17, we will show you how to create an assembly that can be deployed in the global assembly cache (GAC) and thus shared by multiple applications.

Our first custom control is now ready to be used by any page in your Web application. We’ll show you next how to use SimpleControl on a page.

Using a Custom Control on a Page

Using a custom control on a page is similar to using a server control that ships with the SDK, with one difference. The page developer must register a tag prefix (analogous to the asp tag prefix used for standard ASP.NET controls) for your control by using a Register directive at the top of the page, as shown in the following example:

<%@ Register TagPrefix="msp" Namespace="MSPress.ServerControls" Assembly="MSPress.ServerControls" %>

The TagPrefix attribute creates an alias that maps to a custom control’s namespace and assembly. A page developer can specify any name for the tag prefix (other than asp) as long as it does not conflict with the name of another tag prefix specified on the page. The Namespace attribute specifies the namespace in which the custom control is declared. The Assembly attribute specifies the assembly into which the control is compiled. Do not use the .dll file extension when specifying the assembly attribute because the file extension is not part of the assembly name. Listing 5-2 shows you a page that uses our first custom control.

<%@ Page Language="C#" %><%@ Register TagPrefix="msp" NameSpace="MSPress.ServerC ontrols" Assembly="MSPress.ServerControls" %>
Here is the output from our first custom control.

Listing 5-2 SimpleControlTest.aspx

We mentioned earlier that you must declare your control in a namespace. You can now see why that is needed. A namespace allows a control to be used declaratively on a page because the tag prefix in the Register directive maps to the namespace in which the control is declared.

To test the page, save it with an .aspx extension, copy it to your Web application, and open it in your browser. If you ran the setup program included with the book’s sample files, you will find SimpleControlTest.aspx in the Chapter5 directory of your BookWeb application. Enter the following URL in your browser’s address bar:

http://localhost/BookWeb/Chapter5/SimpleControlTest.aspx

Figure 5-2 shows how the output should look.

Figure 5-2 SimpleControlTest.aspx page that tests SimpleControl, viewed in a browser (Image unavailable)

Exposing a Property: The PrimeGenerator Control Example

Now that we have seen the main steps for authoring and deploying a server control, we’ll write a control that exposes a property and does some useful work. Our next sample, PrimeGenerator, is a simple server control that computes and displays prime numbers less than or equal to a given number. The main task of our control is to render the computed primes to the client.

A user of our control should be able to specify an upper limit for the primes’ computation. For this purpose, we will expose a property named Number from our control. Properties are accessed similarly to the way fields are, but they are implemented as accessor methods, effectively acting as "smart" fields. (We described the property construct in Chapter 3, "Component Programming Overview.")

Listing 5-3 provides the complete code for the PrimeGenerator control. PrimeGenerator derives from Control, exposes the Number property, and overrides the Render method to output the result of the computation of primes.

using System;using System.Web.UI; namespace MSPress.ServerControls { public class PrimeGenerator : Control { private int _number; public int Number { get {return _number;} set {_number = value;} } protected override void Render(HtmlTextWriter w riter) { // Sieve is a class that computes primes. // We will define this class later. int[] primes = Sieve.GetPrimes(Number); // Notice that we write successive strings to the // output stream instead of concatenating them into // longer strings before writing. This is more efficient // than string concatenation. writer.Write("Primes less than or equal to: "); writer.Write(Number); writer.Write("
"); for (int i = 0; i < primes.Length; i++){ writer.Write(primes[i]); writer.Write(" "); } writer.Write("
"); } }}

Listing 5-3 PrimeGenerator.cs

All that remains to do is implement a utility class that contains the logic for computing primes. The implementation of this class is not important for control authoring; we have included it here for completeness.

Sieve of Eratosthenes:

The sieve of Eratosthenes (circa 275–195 B.C.) is an elegant algorithm for computing primes smaller than a given number. The algorithm proceeds like this: Given a set of positive integers from 2 to N, start with the number 2 and cross out all its multiples. Repeat with each successive number that is not crossed out—and thus must be a prime because it has no factors smaller than itself. When you are finished, you will be left with only prime numbers less than or equal to N. Notice that when you get to a prime number i, you have to consider only its multiples with integers j >= i. (This is because multiples with integers j < i have already been considered.) The algorithm terminates when you reach a prime greater than the square root of N.

We expose the prime computation functionality from an independent class named Sieve because that functionality does not belong in a control. Listing 5-4 shows the code for the Sieve class.

using System;using System.Collections; namespace MSPress.ServerControls { // Sieve is a utility class that uses the sieve of Eratos thenes // algorithm to compute primes less than or equal to // a given positive integer. internal sealed class Sieve { private Sieve() { } public static int[] GetPrimes(int n) { // Use an array of n+1 bits to correspond to // the numbers from 0 to n. Initially, set all the bits // to true. The goal of the computation is to cycle throu gh // the bit array using the sieve of Eratosthenes algorith m // and to set the bits corresponding to nonprimes to fals e. // The remaining true bits represent primes. BitArray flags = new BitArray(n+1, true); for (int i=2; i <= (int)Math.Sqrt(n); i++){ if (flags[i]){ for (int j = i; j*i <= n; j++) { flags[i*j]= false; } } } // Count the number of primes <= n. int count = 0; for (int i=2; i <= n; i++) { if (flags[i]) count++; } // Create an int array to store the primes. int[] primes = new int[count]; // Check bit flags and populate primes // array with numbers corresponding to // true bits. for (int i=2, j = 0; j < count; i++) { if (flags[i]) primes[j++] = i; } return primes; } }}

Listing 5-4 Sieve.cs (Image unavailable)

Deriving from WebControl

If we derive our custom control from WebControl instead of from Control, our control inherits many additional properties, such as Font, Height, Width, and other style- related properties that enable a page developer to customize the visual appearance of the control. When deriving from WebControl, keep the following stipulations in mind:

Include a reference to the System.Web.UI.WebControls namespace.

Do not directly write to the output stream by overriding the Render method because the Render method of WebControl implements logic to render the outer tag with style information. Instead, override RenderContents if you want to provide content to render within the control’s tags. We will explain this in more detail in Chapter 8.

Override the TagKey property or the TagName property (in the case of a nonstandard HTML tag) inherited from WebControl if you want to render a tag that is different from . By default, WebControl renders an HTML tag. In our example, we will not override either of these properties.

Listing 5-5 highlights the changes to our control when it derives from WebControl.

using System;using System.Web.UI;using System.Web.UI.WebControls; namespace MSPress.ServerControls { public class StyledPrimeGenerator : WebControl { private int _number; public int Number{ get {return _number;} set {_number = value;} } protected override void RenderContents(HtmlTextWriter writer) { // Note that the implementation of the RenderContents // method is identical to the implementation of Render in // PrimeGenerator. int[] primes = Sieve.GetPrimes(Number); writer.Write("Primes less than or equal to: "); writer.Write(Number); writer.Write("
"); for (int i=0; i"); } }}

Listing 5-5 StyledPrimeGenerator.cs

Test Page for the PrimeGenerator Control

The page shown in Listing 5-6 tests the PrimeGenerator and StyledPrimeGenerator controls. Note that StyledPrimeGenerator inherits properties such as Height, Width, ForeColor, and BackColor for free because it derives from WebControl.

<%@ Page Language="C#" %><%@ Register TagPrefix="msp" NameSpace="MSPress.ServerC ontrols" Assembly="MSPress.ServerControls" %>






Enter 3 positive integers:

Listing 5-6 PrimeGeneratorTest.aspx (Image unavailable)

When you access PrimeGeneratorTest.aspx, the output in your browser should be similar to that shown in Figure 5-3. The third output block is rendered by StyledPrimeGenerator, which is visually distinct because of values assigned to some of its style properties.

Figure 5-3 The PrimeGeneratorTest.aspx page that tests the PrimeGenerator and StyledPrimeGenerator controls, viewed in a browser (Image unavailable)

Choosing the Base Class for Your Control

These guidelines will help you determine the base class from which to derive your control:

Derive from System.Web.UI.Control if your control renders nonvisual elements or renders to a non-HTML client. The and tags are examples of nonvisual rendering.

Derive from System.Web.UI.WebControls.WebControl if you want to render HTML that generates a visual interface on the client.

Derive from an existing control—such as Label, Button, and TextBox—when you want to extend or modify the functionality of that control. You can derive from any control in the System.Web.UI.WebControls namespace or from a custom control. However, do not derive from controls in the System.Web.UI.HtmlControls namespace. Controls that derive directly or indirectly from HtmlControl are not allowed in the Visual Studio .NET designer because they break the HTML control model. HTML controls are intended to appear without a tag prefix in declarative page syntax (such as

Read More Show Less

Table of Contents

Dedication;
Foreword;
Acknowledgments;
Nikhil Kothari’s Acknowledgments;
Vandana Datye’s Acknowledgments;
Introduction;
Prerequisites;
Structure of the Book;
Sample Files;
Creating an IIS Virtual Directory;
Tools for Control Authoring and Related Tasks;
Other Resources;
Support;
Overview;
Chapter 1: ASP.NET Overview;
1.1 The .NET Framework;
1.2 A Quick Tour of ASP.NET;
1.3 HTTP Runtime—Request Processing in an ASP.NET Application;
1.4 Extending ASP.NET;
1.5 Summary;
Chapter 2: Page Programming Model;
2.1 A Sample Page;
2.2 Server Controls;
2.3 From Text to Controls;
2.4 Code Model;
2.5 Page Execution Model;
2.6 ASP.NET Pages in a Visual Designer;
2.7 Summary;
Chapter 3: Component Programming Overview;
3.1 Managed Component Overview;
3.2 Properties;
3.3 Methods;
3.4 Events;
3.5 Metadata Attributes;
3.6 Designable Components;
3.7 Summary;
Server Controls—First Steps;
Chapter 4: User Controls: From Page to Control;
4.1 Converting a Page to a User Control;
4.2 Reusable User Controls: The SiteHeader and SiteFooter Examples;
4.3 The User Control Model;
4.4 Deploying a User Control;
4.5 An Application-Specific User Control: The CruiseSelector Example;
4.6 Relative URLs in User Controls;
4.7 Programmatically Instantiating a User Control;
4.8 Caching a User Control;
4.9 Summary;
Chapter 5: Developing a Simple Custom Control;
5.1 Server Control Overview;
5.2 A Trivial Server Control Example;
5.3 Compiling and Deploying a Server Control;
5.4 Exposing a Property: The PrimeGenerator Control Example;
5.5 Choosing the Base Class for Your Control;
5.6 Applying Design-Time Attributes;
5.7 Custom Controls in Visual Studio .NET;
5.8 Debugging a Server Control;
5.9 Summary;
Chapter 6: Custom Controls vs. User Controls;
6.1 Deployment;
6.2 Authoring;
6.3 Content and Layout;
6.4 Design-Time Behavior;
6.5 Performance;
6.6 Summary;
Server Controls—Nuts and Bolts;
Chapter 7: Simple Properties and View State;
7.1 View State and State Management;
7.2 Declarative Persistence of Simple Properties;
7.3 Properties Inherited from Control and WebControl;
7.4 Design-Time Attributes for Properties;
7.5 Putting It Together—The PageTracker Example;
7.6 Summary;
Chapter 8: Rendering;
8.1 Base Classes and Rendering;
8.2 Rendering Methods of the Control Class;
8.3 Overriding Render—The MetaTag Control Example;
8.4 HtmlTextWriter and Related Enumerations;
8.5 Rendering Methods of WebControl;
8.6 Rendering a Web Control—The HoverLabel Example;
8.7 Exercising HtmlTextWriter—The LoginUI Example;
8.8 Downlevel Rendering;
8.9 Summary;
Chapter 9: Control Life Cycle, Events, and Postback;
9.1 Control Life Cycle;
9.2 Events in Server Controls;
9.3 Postback Architecture;
9.4 Mapping a Postback Event to a Server Event—The IPostBackEventHandler Interface;
9.5 Optimizing Event Implementation;
9.6 Generating Client-Side Script for Postback;
9.7 IPostBackDataHandler and Postback Data;
9.8 Putting It Together—The Login Example;
9.9 Exposing Other Semantic Events—The HitTracker Example;
9.10 Summary;
Chapter 10: Complex Properties and State Management;
10.1 Subproperties;
10.2 Properties and Type Converters;
10.3 State Management, IStateManager, and the ViewState Dictionary;
10.4 Implementing IStateManager in a Custom Type;
10.5 Collection Properties—The ImageMap Example;
10.6 Expando Attributes—The IAttributeAccessor Interface;
10.7 Summary;
Chapter 11: Styles in Controls;
11.1 Styles Overview;
11.2 Overriding Style Properties—The Spreadsheet Example;
11.3 Implementing a Custom Typed Style—The MyPanelStyle Example;
11.4 Summary;
Chapter 12: Composite Controls;
12.1 Composite Controls—Key Concepts;
12.2 Implementing a Composite Control—The CompositeLogin Example;
12.3 APIs Related to Composite Controls;
12.4 View State and Child Controls;
12.5 Event Bubbling;
12.6 Styles in Composite Controls—The StyledCompositeLogin Example;
12.7 Templated Controls Overview;
12.8 Implementing a Templated Control—The ContactInfo Example;
12.9 Control Parsing and Control Builders;
12.10 Summary;
Chapter 13: Client-Side Behavior;
13.1 Browser Capabilities and Client-Side Behavior;
13.2 Client Script–Related API;
13.3 Using Client Script and DHTML;
13.4 Deploying Client Files;
13.5 Putting It Together—The HtmlEditor Example;
13.6 Summary;
Chapter 14: Validator Controls;
14.1 Validation Architecture—IValidator, BaseValidator, and CustomValidator;
14.2 The Validation Framework;
14.3 Validating Text Entry—The StringValidator Example;
14.4 Summary;
Chapter 15: Design-Time Functionality;
15.1 .NET Framework Design-Time Architecture;
15.2 Type Converters;
15.3 Designers;
15.4 UI Type Editors;
15.5 Component Editors;
15.6 Debugging Design-Time Code;
15.7 Summary;
Chapter 16: Data-Bound Controls;
16.1 Data Binding Overview;
16.2 Implementing a Data-Bound Control;
16.3 Implementing a Data-Bound Control Designer;
16.4 Summary;
Chapter 17: Localization, Licensing, and Other Miscellany;
17.1 Localization;
17.2 Licensing;
17.3 Configurable Properties;
17.4 Deployment;
17.5 Summary;
Server Components;
Chapter 18: XML Web Services;
18.1 XML Web Services Overview;
18.2 Developing an XML Web Service—The StockWebService Example;
18.3 XML Web Service–Based Server Controls—The StockGrid Example;
18.4 Summary;
Chapter 19: HTTP Handlers;
19.1 HTTP Handler Overview;
19.2 The "Hello, World" HTTP Handler Example;
19.3 Handling a New Extension—The XmlHandler Example;
19.4 Dynamic Images—The ImageLabelHandler Example;
19.5 HTTP Handlers and Session State;
19.6 Summary;
Server Control Case Studies;
Chapter 20: Data-Bound Templated Controls;
20.1 The ListView Control;
20.2 ListView Specification;
20.3 ListView Implementation;
20.4 Summary;
Chapter 21: DHTML-Based Server Controls;
21.1 The DatePicker Control;
21.2 DatePicker Specification;
21.3 DatePicker and DatePickerDesigner Implementation;
21.4 Summary;
Appendixes;
Metadata Attributes;
Design-Time Attributes;
Parse-Time Attributes;
Object Model for Common Classes;
Microsoft ASP.NET Web Matrix;
Web Matrix Features;
Web Matrix for Component Developers;
Summary;
About the Authors;
Nikhil Kothari;
Vandana Datye;
Folding Ruler;

Read More Show Less

First Chapter

Developing a Simple Custom Control
  • Server Control Overview
  • A Trivial Server Control Example
  • Compiling and Deploying a Server Control
    • Using a Custom Control on a Page
  • Exposing a Property: The PrimeGenerator Control Example
    • Deriving from WebControl
    • Test Page for the PrimeGenerator Control
  • Choosing the Base Class for Your Control
  • Applying Design-Time Attributes
    • Applying TagPrefixAttribute
  • Custom Controls in Visual Studio .NET
    • Adding a Custom Control to the Toolbox
    • Using Custom Controls from the Toolbox
    • Customizing the Toolbox Icon
  • Debugging a Server Control
  • Summary

5  Developing a Simple Custom Control

In Chapter 4, "User Controls: From Page to Control," we described declaratively authored user controls that are deployed as text files (.ascx and optional code- behind files). In this chapter, we will describe controls that are authored in code and deployed in the form of compiled class libraries. To differentiate between the two control authoring models, we will use the term custom control when referring to a control that is authored as a managed class and compiled before deployment.

You can develop custom controls by using any code editor and the .NET Framework SDK. In this chapter, we will describe the essential steps for authoring a custom control and show you how to enable design-time features that give your control a professional look and feel when it is used in a designer such as Visual Studio .NET. We will also show you how to compile a custom control using command-line tools that ship with the .NET Framework SDK. In addition, we’ll describe how to debug a server control using command-line tools and using Visual Studio .NET. Because this chapter focuses on programming, we will not get into the details of authoring a server control in Visual Studio .NET. You can see those details in the topic "Walkthrough: Creating a Web Custom Control" in the .NET Framework SDK or MSDN documentation.

Server Control Overview

An ASP.NET server control is a component that executes program logic on the server, provides a programmable object model, and renders markup text (such as HTML, XML, and WML) to a Web browser client or other viewing device. A server control is a fundamental building block of an ASP.NET Web application. Although a significant amount of plumbing is needed to enable a class to interact with the ASP.NET page framework and to participate in an HTTP request/response scenario, ASP.NET frees you from low-level details by providing a base class (System.Web.UI.Control) that implements the necessary plumbing. To author a server control, you must define a class that directly or indirectly derives from System.Web.UI.Control. All ASP.NET controls that ship with the .NET Framework SDK derive from Control or from one of its derived classes.

Figure 5-1 shows the hierarchy of the base classes for server controls. The full class hierarchy containing all the server controls in ASP.NET is shown in Chapter 2, "Page Programming Model."

Figure 5-1 Hierarchy of the base classes for server controls (Image unavailable)

The Control class provides the basic functionality for participating in the page framework. In particular, it provides the functionality that allows a server control to be placed within the control tree that represents an .aspx page. The Control class also implements the System.ComponentModel.IComponent interface, which makes it a designable component. A designable component can be added to the toolbox of a visual designer, can be dragged onto a design surface, can display its properties in a property browser, and can provide other kinds of design-time support.

The WebControl class adds functionality to the base Control class for rendering HTML content. WebControl provides support for styles through properties such as Font, Height, Width, BackColor, and ForeColor. Later in this chapter, in the "Choosing the Base Class for Your Control" section, we will provide scenario-based guidelines to help you determine the base control class from which you should derive your control.

A Trivial Server Control Example

To demonstrate the mechanics of implementing a control, we’ll start by creating a very simple server control that merely renders a text string to the client. Our control derives from the base Control class to participate in the HTTP request/response processing provided by the page framework and overrides the inherited Render method to write to the output text stream. Listing 5-1 shows the code for our control.

using System;
using System.Web.UI;
 
namespace MSPress.ServerControls {
    public class SimpleControl : Control {
        protected override void Render(HtmlTextWriter w riter) {
            writer.Write("I don’t do anything useful, " );
            writer.Write("but at least I’m a control... ");
        }
    }
}

Listing 5-1 SimpleControl.cs


NOTE:
If you are using Visual Studio .NET, start a new Microsoft Visual C# Control Library project, delete the designer-generated code in WebCustomControl1.cs, and replace it with the code we provide for the control.

System.Web.UI.HtmlTextWriter is a utility class that encapsulates the functionality of writing HTML to a text stream. In Chapter 8, "Rendering," we will show you how to use the methods of the HtmlTextWriter class to simplify HTML rendering. For now, SimpleControl simply passes text into the Write method of the HtmlTextWriter instance. The Write method outputs the specified text to the HTTP response stream and is equivalent to the Response.Write method in traditional Active Server Pages programming. Do not directly invoke Page.Response.Write from your controls because doing so breaks the encapsulation provided by the page framework. Instead, override one of the rendering methods provided by the Control or WebControl class to write to the response stream. We’ll explain the rendering process in greater detail in Chapter 8.

The using declarations enable you to access types by shorter names instead of their fully qualified class names. Thus, Control is equivalent to System.Web.UI.Control. The using declarations do not add any overhead, and they make your code more readable. You must declare your control in a namespace so that page developers can use your control declaratively on pages, as you will soon see.

The Render method, which SimpleControl overrides, corresponds to the Render phase in a control’s life cycle. A control writes text to the underlying HTTP response stream during this phase.

Compiling and Deploying a Server Control

For a custom control to be usable on a page, the control must be compiled into an assembly and made accessible to the ASP.NET runtime. If you are not familiar with the concept of assembly, think of it as a dynamic-link library (DLL) implemented in managed code.

In this book’s sample files, we have provided batch files for building from the command line and provided a Visual Studio .NET solution file (BookCodeCS.sln for C#) for opening the project in Visual Studio .NET. We will discuss the command-line procedure in this section, and we’ll show how to use a custom control in Visual Studio .NET in the section "Custom Controls in Visual Studio .NET."

The batch files in the book’s sample files contain commands that will compile all the control samples in this book. If you want to get a feel for building a server control assembly, follow the instructions in the next paragraph. However, before executing the commands, copy the source files for the control samples in this chapter to a directory other than the one in which you installed the source code so that you don’t overwrite the installed files.

To compile the control shown in Listing 5-1, navigate to the directory that contains the source file for SimpleControl (for example, C:\MyBookCodeCS\MyServerControls) and execute the following command:

csc /t:library /out:MSPress.ServerControls.dll / r:System.dll 
    /r:System.Web.dll SimpleControl.cs 

The csc command invokes the C# compiler. The /t option tells the compiler that the target assembly is a library. The /out option provides the name of the output file. The /r option provides the names of the assemblies whose metadata is referenced by the classes being compiled. At this point, we need to reference only two assemblies: System and System.Web. When you execute the compiler command, it will generate a library assembly named MSPress.ServerControls in the file MSPress.ServerControls.dll.

Each ASP.NET application has a special location from which it can access private assemblies. (We’ll explain what private means shortly.) That location is the bin directory immediately under the virtual root representing an Internet Information Services (IIS) Web application. If your Web application’s virtual root is named BookWeb and maps to a path such as C:\BookWebDir, the directory C:\BookWebDir\bin should hold assemblies referenced by pages in the BookWeb Web directory. Binaries that are needed by pages in subdirectories must also be placed in the bin directory directly under the virtual root. For example, the bin directory for pages in C:\BookWebDir\Chapter5 is also C:\BookWebDir\bin. If you ran the setup program included with the book’s sample files, the BookWeb Web application and its bin directory are already created for you.

If you want to follow the instructions in this chapter to understand the mechanics of the process, create an IIS virtual root different from the BookWeb application that was created for you when you installed the samples. If you have not created an IIS virtual root before, see the Introduction of this book for instructions. It is important that you create a new Web application (such as MyBookWeb) so that you don’t overwrite the pages and binaries that are part of the BookWeb application. You must also create a directory named bin under the virtual root.

Next copy the MSPress.ServerControls.dll file that you created earlier to the bin directory of your Web application. Here’s an example:

copy MSPress.ServerControls.dll <path to the root of your Web application>\bin

The assembly that you created and copied into the application’s bin directory is known as a private assembly because only pages in your Web application can reference it. In Chapter 17, we will show you how to create an assembly that can be deployed in the global assembly cache (GAC) and thus shared by multiple applications.

Our first custom control is now ready to be used by any page in your Web application. We’ll show you next how to use SimpleControl on a page.

Using a Custom Control on a Page

Using a custom control on a page is similar to using a server control that ships with the SDK, with one difference. The page developer must register a tag prefix (analogous to the asp tag prefix used for standard ASP.NET controls) for your control by using a Register directive at the top of the page, as shown in the following example:

<%@ Register TagPrefix="msp" Namespace="MSPress.ServerControls"
  Assembly="MSPress.ServerControls" %>

The TagPrefix attribute creates an alias that maps to a custom control’s namespace and assembly. A page developer can specify any name for the tag prefix (other than asp) as long as it does not conflict with the name of another tag prefix specified on the page. The Namespace attribute specifies the namespace in which the custom control is declared. The Assembly attribute specifies the assembly into which the control is compiled. Do not use the .dll file extension when specifying the assembly attribute because the file extension is not part of the assembly name. Listing 5-2 shows you a page that uses our first custom control.

<%@ Page Language="C#" %>
<%@ Register TagPrefix="msp" NameSpace="MSPress.ServerC ontrols" 
  Assembly="MSPress.ServerControls" %>
<html>
  <body>
    <br>
    Here is the output from our first custom control.
    <br>
    <msp:SimpleControl id="simple1" runat="server" />
    <br>
  </body>
</html>

Listing 5-2 SimpleControlTest.aspx

We mentioned earlier that you must declare your control in a namespace. You can now see why that is needed. A namespace allows a control to be used declaratively on a page because the tag prefix in the Register directive maps to the namespace in which the control is declared.

To test the page, save it with an .aspx extension, copy it to your Web application, and open it in your browser. If you ran the setup program included with the book’s sample files, you will find SimpleControlTest.aspx in the Chapter5 directory of your BookWeb application. Enter the following URL in your browser’s address bar:

http://localhost/BookWeb/Chapter5/SimpleControlTest.aspx

Figure 5-2 shows how the output should look.

Figure 5-2 SimpleControlTest.aspx page that tests SimpleControl, viewed in a browser (Image unavailable)

Exposing a Property: The PrimeGenerator Control Example

Now that we have seen the main steps for authoring and deploying a server control, we’ll write a control that exposes a property and does some useful work. Our next sample, PrimeGenerator, is a simple server control that computes and displays prime numbers less than or equal to a given number. The main task of our control is to render the computed primes to the client.

A user of our control should be able to specify an upper limit for the primes’ computation. For this purpose, we will expose a property named Number from our control. Properties are accessed similarly to the way fields are, but they are implemented as accessor methods, effectively acting as "smart" fields. (We described the property construct in Chapter 3, "Component Programming Overview.")

Listing 5-3 provides the complete code for the PrimeGenerator control. PrimeGenerator derives from Control, exposes the Number property, and overrides the Render method to output the result of the computation of primes.

using System;
using System.Web.UI;
 
namespace MSPress.ServerControls {
    public class PrimeGenerator : Control {
        private int _number;
        public int Number {
            get {return _number;}
            set {_number = value;}
        }
        protected override void Render(HtmlTextWriter w riter) {
            // Sieve is a class that computes primes.
            // We will define this class later.
            int[] primes = Sieve.GetPrimes(Number);
            //  Notice that we write successive strings to the
            //  output stream instead of concatenating them into 
            //  longer strings before writing. This is more efficient
             // than string concatenation.
            writer.Write("Primes less than or equal to:  ");
            writer.Write(Number);
            writer.Write("<br>");
            for (int i = 0; i < primes.Length; i++){
                writer.Write(primes[i]);
                writer.Write(" ");
            }
            writer.Write("<br>");
        }
    }
}

Listing 5-3 PrimeGenerator.cs

All that remains to do is implement a utility class that contains the logic for computing primes. The implementation of this class is not important for control authoring; we have included it here for completeness.

Sieve of Eratosthenes:
The sieve of Eratosthenes (circa 275–195 B.C.) is an elegant algorithm for computing primes smaller than a given number. The algorithm proceeds like this: Given a set of positive integers from 2 to N, start with the number 2 and cross out all its multiples. Repeat with each successive number that is not crossed out—and thus must be a prime because it has no factors smaller than itself. When you are finished, you will be left with only prime numbers less than or equal to N. Notice that when you get to a prime number i, you have to consider only its multiples with integers j >= i. (This is because multiples with integers j < i have already been considered.) The algorithm terminates when you reach a prime greater than the square root of N.

We expose the prime computation functionality from an independent class named Sieve because that functionality does not belong in a control. Listing 5-4 shows the code for the Sieve class.

using System;
using System.Collections;
 
namespace MSPress.ServerControls {
    //  Sieve is a utility class that uses the sieve of Eratos thenes
    //  algorithm to compute primes less than or equal to
    // a given positive integer.
    internal sealed class Sieve {
        private Sieve() { }
        public static int[] GetPrimes(int n) {     
            //  Use an array of n+1 bits to correspond to
            //  the numbers from 0 to n. Initially, set all the bits 
            //  to true. The goal of the computation is to cycle throu gh
            //  the bit array using the sieve of Eratosthenes algorith m
            //  and to set the bits corresponding to nonprimes to fals e.
             //  The remaining true bits represent primes.             
            BitArray flags = new BitArray(n+1, true); 
            for (int i=2; i <= (int)Math.Sqrt(n); i++){          
                if (flags[i]){
                    for (int j = i; j*i <= n; j++) {
                        flags[i*j]= false;                   
                    }
                }
            }
 
            // Count the number of primes <= n.
            int count = 0;     
            for (int i=2; i <= n; i++) {         
                if (flags[i]) count++;
            }
            
            // Create an int array to store the primes.
            int[] primes = new int[count];
 
            // Check bit flags and populate primes 
            // array with numbers corresponding to  
            // true bits.
            for (int i=2, j = 0; j < count; i++) {        
                if (flags[i]) primes[j++] = i;
            }
            return  primes;
        }  
    }
}

Listing 5-4 Sieve.cs (Image unavailable)

Deriving from WebControl

If we derive our custom control from WebControl instead of from Control, our control inherits many additional properties, such as Font, Height, Width, and other style- related properties that enable a page developer to customize the visual appearance of the control. When deriving from WebControl, keep the following stipulations in mind:

  • Include a reference to the System.Web.UI.WebControls namespace.
  • Do not directly write to the output stream by overriding the Render method because the Render method of WebControl implements logic to render the outer tag with style information. Instead, override RenderContents if you want to provide content to render within the control’s tags. We will explain this in more detail in Chapter 8.
  • Override the TagKey property or the TagName property (in the case of a nonstandard HTML tag) inherited from WebControl if you want to render a tag that is different from <span>. By default, WebControl renders an HTML <span> tag. In our example, we will not override either of these properties.

Listing 5-5 highlights the changes to our control when it derives from WebControl.

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace MSPress.ServerControls {
    public class StyledPrimeGenerator : WebControl {
        private int _number;
        public int Number{
            get {return _number;}
            set {_number = value;}
        }
        
        protected override void RenderContents(HtmlTextWriter writer) {
            //  Note that the implementation of the RenderContents 
            //  method is identical to the implementation of Render in  
            // PrimeGenerator.
            int[] primes = Sieve.GetPrimes(Number);
            writer.Write("Primes less than or equal to:  ");
             writer.Write(Number);
            writer.Write("<br>");
            for (int i=0; i<primes.Length; i++){
                writer.Write(primes[i]);
                writer.Write(" ");
            }
            writer.Write("<br>");
        }
    }
}

Listing 5-5 StyledPrimeGenerator.cs

Test Page for the PrimeGenerator Control

The page shown in Listing 5-6 tests the PrimeGenerator and StyledPrimeGenerator controls. Note that StyledPrimeGenerator inherits properties such as Height, Width, ForeColor, and BackColor for free because it derives from WebControl.

<%@ Page Language="C#" %>
<%@ Register TagPrefix="msp" NameSpace="MSPress.ServerC ontrols" 
  Assembly="MSPress.ServerControls" %>
<html>
  <head>
      <script runat="server">
        void ButtonClicked(object sender, EventArgs e)  {
            primegen1.Number = Int32.Parse(num1.Text);
            primegen2.Number = Int32.Parse(num2.Text);
            sprimegen1.Number = Int32.Parse(num3.Text);
        }
      </script>
  </head>
  <body>
    <form runat="server">
      <br>
      <br>
      <msp:PrimeGenerator Number="15" id="primegen1" ru nat="server" />
      <br>
      <msp:PrimeGenerator Number="100" id="primegen2" r unat="server" />
      <br>
      <msp:StyledPrimeGenerator  Number="51" id="sprimeg en1" 
        Width="500" Font-Name="Verdana" Font- Size="14pt" 
        BackColor="#EEEEEE" ForeColor="Black" runat="se rver" />
      <br>
      Enter 3 positive integers:
      <asp:TextBox id="num1" width="50" text="0" runat= "server" />
      <asp:TextBox id="num2" width="50" text="0" runat= "server" />
      <asp:TextBox id="num3" width="50" text="0" runat= "server" />
      <br>
      <asp:Button text="Submit" id="submit" 
        onclick="ButtonClicked" runat="server" />
      <br>
    </form>
  </body>
</html>

Listing 5-6 PrimeGeneratorTest.aspx (Image unavailable)

When you access PrimeGeneratorTest.aspx, the output in your browser should be similar to that shown in Figure 5-3. The third output block is rendered by StyledPrimeGenerator, which is visually distinct because of values assigned to some of its style properties.

Figure 5-3 The PrimeGeneratorTest.aspx page that tests the PrimeGenerator and StyledPrimeGenerator controls, viewed in a browser (Image unavailable)

Choosing the Base Class for Your Control

These guidelines will help you determine the base class from which to derive your control:

  • Derive from System.Web.UI.Control if your control renders nonvisual elements or renders to a non-HTML client. The <meta> and <xml> tags are examples of nonvisual rendering.
  • Derive from System.Web.UI.WebControls.WebControl if you want to render HTML that generates a visual interface on the client.
  • Derive from an existing control—such as Label, Button, and TextBox—when you want to extend or modify the functionality of that control. You can derive from any control in the System.Web.UI.WebControls namespace or from a custom control. However, do not derive from controls in the System.Web.UI.HtmlControls namespace. Controls that derive directly or indirectly from HtmlControl are not allowed in the Visual Studio .NET designer because they break the HTML control model. HTML controls are intended to appear without a tag prefix in declarative page syntax (such as <Button runat="server" />). However, all custom controls—including those deriving from HtmlControl or its descendants—require a tag prefix when used declaratively on a page.

The object models for the Control and WebControl base classes are described in Appendix B, "Object Model for Key Classes."

Applying Design-Time Attributes

Although the PrimeGenerator control works as expected on an .aspx page, you will find that if you use it in a visual designer such as Visual Studio. NET (which we’ll demonstrate in the next section), it lacks some standard features that are expected at design time. For example, you might expect the Number property to be automatically highlighted when a page developer clicks the control on the design surface. To get this and other design-time features, you have to provide metadata that the designer uses to improve the design-time experience. The .NET Framework enables metadata to be supplied for a class and its members through a feature known as attributes. (We described metadata attributes in Chapter 3.) We have marked PrimeGenerator with design-time attributes (in square brackets) in the following code:

(Code unavailable)

DefaultPropertyAttribute specifies the default property for the control, and ToolboxDataAttribute specifies the tag that is written to the page when the control is dragged from the toolbox onto the design surface. ToolboxDataAttribute is optional; if this attribute is not applied, the designer generates a standard tag to the page.

We will discuss design-time attributes in more detail in Chapter 15, "Design- Time Functionality." Appendix A, "Metadata Attributes," provides information about the syntax and usage of attributes commonly applied to controls. In this chapter, we’ll describe only one attribute—TagPrefixAttribute—in more detail because it is especially important at design time.

Applying TagPrefixAttribute

TagPrefixAttribute is an assembly-level attribute that provides a tag prefix that a designer uses for a control when it is dragged from the toolbox onto the design surface. If this attribute is not applied, the designer generates a default tag prefix such as "cc1" on the page. Because TagPrefixAttribute is an assembly-level attribute, it is not applied directly to any particular control; instead, it is declared in a separate file that is compiled into the same assembly as the control.

The TagPrefixAttribute attribute is already applied to the sample controls in the book’s sample files. If you are re-creating the controls in this chapter to walk through the steps for compilation and deployment, you can apply this attribute as described next.

To apply TagPrefixAttribute in Visual Studio .NET, edit the AssemblyInfo.cs file in your project to include the following lines of code and rebuild your control project:

using System.Web.UI;
[assembly:TagPrefix("MSPress.ServerControls", "msp")] 

The tag prefix just shown associates the msp tag prefix with the namespace MSPress.ServerControls so that the tag prefix is generated when a user drags and drops your controls from the toolbox onto a page.

If you are building from the command line, create a file named AssemblyInfo.cs and place it in the directory that contains the source files for your controls (for example, C:\MyBookCodeCs\MyServerControls). This file does not necessarily have to be named AssemblyInfo.cs, but for consistency with Visual Studio .NET projects, we recommend that you give it this name.

Add the following code to AssemblyInfo.cs, and save the file:

// AssemblyInfo.cs
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Web.UI;
//
// General information about an assembly is controlled 
// through assembly-level attributes. 
//  The TagPrefixAttribute associates a tag prefix with a 
//  namespace. If you have multiple control namespaces in  a single
//  assembly, you will need a TagPrefixAttribute correspon ding
// to each namespace.
[assembly:TagPrefix("MSPress.ServerControls", "msp")] 

Recompile the code for your controls and for AssemblyInfo.cs into an assembly using the same command that you used earlier:

csc /t:library /out:MSPress.ServerControls.dll / r:System.dll 
    / r:System.Web.dll SimpleControl.cs PrimeGenerator.cs 
    StyledPrimeGenerator.cs AssemblyInfo.cs

See the instructions outlined earlier in the chapter in the section "Compiling and Deploying a Server Control" to make sure that you do not overwrite the assembly generated by the batch file you downloaded with the book’s sample files.

The Register directive with the tag prefix specified in the TagPrefixAttribute is generated only when the control is dragged and dropped onto a page in the designer. If you author pages in a text editor outside the designer, you must manually add the Register directive. The next section shows how the TagPrefixAttribute is used by a visual designer such as Visual Studio .NET.

Custom Controls in Visual Studio .NET

In this section, we’ll show you how to use a custom control in Visual Studio .NET and how you can associate a custom icon with your control.

Adding a Custom Control to the Toolbox

To add PrimeGenerator (or any other custom component) to the Toolbox, perform the following steps:

  1. Open an .aspx page in Design view, and make the Web Forms tab active in the Toolbox.
  2. From the Tools menu, click Customize Toolbox.
  3. In the Customize Toolbox dialog box, click the .NET Framework Components tab.
  4. Click the Browse button on the lower right below the components list.
  5. Navigate to the directory that contains the assembly into which your controls are compiled, and click the name of that assembly (for example, C:\MyBookCodeCS\MyServerControls\MSPress.ServerControls.dll).
  6. You will see that our three controls (PrimeGenerator, SimpleControl, and StyledPrimeGenerator) now appear, along with the other .NET Framework components. Make sure that the boxes next to the control names are checked, as shown in Figure 5-4.
  7. Click OK to close the dialog box. You’ll see that our three controls now appear in the Toolbox under the Web Forms tab.
  8. Figure 5-4 User interface for customizing the Toolbox (Image unavailable)

Using Custom Controls from the Toolbox

To use our custom controls on a page, perform the following steps:

  1. Create a new ASP.NET Web application project. (When you create a Web application, Visual Studio .NET automatically creates an IIS virtual root for you.)
  2. Double-click the WebForm1.aspx file in Solution Explorer so that the page opens in Design view.
  3. Click the Web Forms tab of the Toolbox and you will see that the SimpleControl, PrimeGenerator, and StyledPrimeGenerator controls are now included in the Toolbox.
  4. Drag PrimeGenerator and StyledPrimeGenerator onto the page. When you drag a custom control onto the design surface, Visual Studio .NET copies the assembly that contains the control to your Web application’s bin directory. For example, if your Web application is named MyBookWeb, you will find that MyBookWeb\bin now contains MSPress.ServerControls.dll.

Set some of the style properties of StyledPrimeGenerator in the property browser. In HTML view, you should see page syntax similar to that shown in Listing 5-7. Note that the designer automatically generates the tag prefix msp corresponding to the namespace MSPress.ServerControls, as we specified in the TagPrefixAttribute. If our assembly did not have a TagPrefixAttribute, the designer would generate a default tag prefix such as cc1.

<%@ Register TagPrefix="msp" Namespace="MSPress.ServerC ontrols" 
  Assembly="MSPress.ServerControls" %>
<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" 
  AutoEventWireup="false" Inherits="BookWeb.Chapter5.We bForm1" %>
<!DOCTYPE HTML PUBLIC "-//W3C// DTD HTML 4.0 Transitional//EN" >
<HTML>
  <HEAD>
    <title>WebForm1</title>
    <meta name="GENERATOR" Content="Microsoft Visual St udio 7.0">
    <meta name="CODE_LANGUAGE" Content="C#">
    <meta name="vs_defaultClientScript" content="JavaSc ript">
    <meta name="vs_targetSchema"  
      content="http://schemas.microsoft.com/intellisense/ie5">
  </HEAD>
  <body>
    <form id="WebForm1" method="post" runat="server">
      <msp:PrimeGenerator id="PrimeGenerator1" runat="s erver" 
        Number="91">
      </msp:PrimeGenerator>
      <p>
         <msp:StyledPrimeGenerator id="StyledPrimeGenera tor1" 
          runat="server" Number="329" BackColor="Gainsb oro" 
          Font-Size="Medium" Font- Names="Verdana" Width="300px">
        </msp:StyledPrimeGenerator>
      </p>
    </form>
  </body>
</HTML>

Listing 5-7 Designer-generated HTML for a page that uses PrimeGenerator and StyledPrimeGenerator

Figure 5-5 shows the page in Design view in the Visual Studio .NET environment.

Figure 5-5 A page that uses PrimeGenerator and StyledPrimeGenerator in Design view in Visual Studio .NET (Image unavailable)

Notice that unlike PrimeGenerator, StyledPrimeGenerator has style properties that it inherits from its base class, WebControl. In this example, we have set the ForeColor, BackColor, BorderColor, and BorderStyle properties of the StyledPrimeGenerator instance.

Customizing the Toolbox Icon

Our custom controls appear with default icons (images of gears) in the Toolbox. You can provide a different icon for your control by embedding a bitmap file in the control’s assembly. The bitmap file must contain a 16-by-16 bitmap and must be embedded as a managed resource in the same namespace as the control with which it is associated. The bitmap must be named the same way as its associated control class— for example, PrimeGenerator.bmp. By convention, the lower-left pixel of the bitmap determines its transparent color.

To embed a bitmap into an assembly as a managed resource from the command line, add the bitmap to the directory containing the source files for your control and compile using the /res option:

csc / res:PrimeGenerator.bmp,MSPress.ServerControls.PrimeGene rator.bmp 
    /t:library /out:MSPress.ServerControls.dll / r:System.dll 
    /r:System.Web.dll *.cs 

To embed a bitmap using Visual Studio .NET, add the bitmap to your project and click the bitmap in Solution Explorer. Set the build action to Embedded Resource in the property browser, and rebuild your project.

To see the custom icon in the Toolbox, delete the previous version of your control from the Toolbox, rebuild your control so that the bitmap is embedded in the assembly, and add the control to the Toolbox as before. To delete a control from the Toolbox, you can right-click the control and select the Delete option.

In our example, the visual appearance of our custom controls at design time is the same as the run-time appearance. However, if we want our controls to be displayed differently at design time, we can do so by associating special classes known as designers with our controls. We will describe designers in Chapter 15.

Debugging a Server Control

To debug a server control, you must attach a debugger to an application that uses the server control because server controls are compiled into libraries, while a debugger can be attached only to an executable.

You can debug a server control using the debugging capabilities of the Visual Studio .NET IDE, or, if you have the .NET Framework SDK alone, you can use the graphical debugger DbgClr or the command-line debugger, CorDbg.

To debug a control in Visual Studio .NET, perform the following steps:

  1. Create a solution that contains these projects: a class library that contains the control you want to debug and a Web application that contains a Web Forms page that uses your control. Make sure that you have enabled debugging by specifying the Debug="true" attribute in the Page directive at the top of the page.
  2. Set breakpoints in the source code for your control and build the solution.
  3. In Solution Explorer, right-click the page that uses your control and click Set As Start Page.
  4. From the Debug menu, click Start (or press F5 on the keyboard) to start debugging.

The debugger will stop at the first breakpoint in the code for your control. From there on, you can perform normal debugging operations such as stepping into code and inspecting variables.

The graphical debugger that ships with the .NET Framework SDK, DbgClr, provides the same debugging capabilities as Visual Studio .NET. However, you must manually perform the steps to compile your controls library, to load your Web application and to attach the debugger to the Web application.

To debug a server control using the DbgClr graphical debugger, perform the following steps:

  1. Compile your control using the /debug option. This generates the assembly (.dll) and the program database (.pdb) file that contains debugging information.
  2. Create a Web application and copy the .dll and .pdb files to your Web application’s bin directory.
  3. Create an ASP.NET page that uses the control you want to debug and place it within your Web application. (This step is not needed if your Web application already contains a page or pages that use your control.) Make sure that you have enabled debugging on the page by specifying the Debug="true" attribute in the Page directive at the top of the page.
  4. Start the debugger by opening the FrameworkSDK\GuiDebug directory in Windows Explorer and double-clicking DbgClr.exe.
  5. From the File menu click Open to browse to the file that contains the source code for the control you want to debug, and open that file.

  6. Set breakpoints in the source code of your control.
  7. From the Debug menu click Debug Processes. This will launch the Processes dialog box, which displays running processes to which you can attach the debugger.
  8. Click aspnet_wp.exe to select the ASP.NET worker process and click the Attach button on the right to attach the debugger to it. In Windows .NET Server, you should attach to the IIS worker process, w3wp.exe, which replaces the ASP.NET worker process.
  9. Click the Close button in the upper right corner of the Processes dialog box to close the dialog box.
  10. Open a browser window and request a page that uses your control.

The debugger will stop at the first breakpoint in the code for your control. From there on you can perform normal debugging operations.

Summary

In this chapter, we walked through the process of writing, compiling, using, and debugging a custom control. We examined the Control and WebControl base classes and looked at design-time metadata attributes that modify the appearance and behavior of a control in a visual designer. We looked at custom controls in Visual Studio .NET and saw that a custom control can be added to the toolbox of a design environment and used on a design surface just as a standard ASP.NET control. In Part III of this book, "Server Controls—Nuts and Bolts," we’ll get into the details of control authoring, design-time programming, and deployment so that you can author and distribute professional quality server controls similar to the standard ASP.NET controls.

Read More Show Less

Customer Reviews

Be the first to write a review
( 0 )
Rating Distribution

5 Star

(0)

4 Star

(0)

3 Star

(0)

2 Star

(0)

1 Star

(0)

Your Rating:

Your Name: Create a Pen Name or

Barnes & Noble.com Review Rules

Our reader reviews allow you to share your comments on titles you liked, or didn't, with others. By submitting an online review, you are representing to Barnes & Noble.com that all information contained in your review is original and accurate in all respects, and that the submission of such content by you and the posting of such content by Barnes & Noble.com does not and will not violate the rights of any third party. Please follow the rules below to help ensure that your review can be posted.

Reviews by Our Customers Under the Age of 13

We highly value and respect everyone's opinion concerning the titles we offer. However, we cannot allow persons under the age of 13 to have accounts at BN.com or to post customer reviews. Please see our Terms of Use for more details.

What to exclude from your review:

Please do not write about reviews, commentary, or information posted on the product page. If you see any errors in the information on the product page, please send us an email.

Reviews should not contain any of the following:

  • - HTML tags, profanity, obscenities, vulgarities, or comments that defame anyone
  • - Time-sensitive information such as tour dates, signings, lectures, etc.
  • - Single-word reviews. Other people will read your review to discover why you liked or didn't like the title. Be descriptive.
  • - Comments focusing on the author or that may ruin the ending for others
  • - Phone numbers, addresses, URLs
  • - Pricing and availability information or alternative ordering information
  • - Advertisements or commercial solicitation

Reminder:

  • - By submitting a review, you grant to Barnes & Noble.com and its sublicensees the royalty-free, perpetual, irrevocable right and license to use the review in accordance with the Barnes & Noble.com Terms of Use.
  • - Barnes & Noble.com reserves the right not to post any review -- particularly those that do not follow the terms and conditions of these Rules. Barnes & Noble.com also reserves the right to remove any review at any time without notice.
  • - See Terms of Use for other conditions and disclaimers.
Search for Products You'd Like to Recommend

Recommend other products that relate to your review. Just search for them below and share!

Create a Pen Name

Your Pen Name is your unique identity on BN.com. It will appear on the reviews you write and other website activities. Your Pen Name cannot be edited, changed or deleted once submitted.

 
Your Pen Name can be any combination of alphanumeric characters (plus - and _), and must be at least two characters long.

Continue Anonymously
Sort by: Showing 1 Customer Reviews
  • Anonymous

    Posted December 17, 2002

    Some Revelation of Shrouded Topic

    With the release of ASP .NET the creation of Web Server Controls will be a major concern in the initial development of systems. This book actually provides some insight into this process which has been missing in the .NET documentation. However you must be prepared to dig the information out. The first thing to note is that the example code is not included with the book but is to be downloaded and the site URL given is not correct. Secondly the common phrases in the book seems to be 'We will discuss this later' or ... 'as discussed'. You will find yourself having to jump around in the book alot. This is not suprising considering the complexity of the subject. Third when discussing the coding of a designer the class created is for a Windows Form control not a Web Server Control. Obviously this code needs to be updated when using the samples. Lastly the book in general throws code at you and covers it at a high level. Much of this information can be dug out of the .NET documentation. What this book does offer is a central location to turn to for information on building Web Server Controls which requires a lot of hunting through the documentation supplied with the product. This book can therefore save you a lot of hunt and seek time and make the development leanring curve a little better.

    Was this review helpful? Yes  No   Report this review
Sort by: Showing 1 Customer Reviews

If you find inappropriate content, please report it to Barnes & Noble
Why is this product inappropriate?
Comments (optional)