Building ASP.NET User and Server Controls — Part 1

By Solomon Shaffer

The introduction of .NET has led to many changes, including the way we work with forms and controls. This is especially true in the Internet realm because this environment is trying desperately to catch up with the interactive feel of traditional Windows forms-based applications.

Microsoft has taken great strides to achieve this goal with tools such as the ASP.NET ViewState and object caching. Another goal is to make the toolset to build these Internet applications very useful and broad. One of the tools that are afforded to us is ASP.NET user controls and the ability to treat these controls as actual objects within our applications. This article will explore how user controls can be practical and will lay the groundwork for building more complex controls in the future.

What Is an ASP.NET User Control?

If you have been dabbling in ASP.NET for any time, you have probably heard myriad definitions for a “user control.” Why not add one more to the list? An ASP.NET user control is a group of one or more server controls or static HTML elements that encapsulate a piece of functionality. A user control could simply be an extension of the functionality of an existing server control(s) (such as an image control that can be rotated or a calendar control that stores the date in a text box). Or, it could consist of several elements that work and interact together to get a job done (such as several controls grouped together that gather information about a user’s previous work experience).

In either case, a user control typically resides on a page with other elements. This breakup of functionality could be the basis of an entire application built with independent and reusable user controls. The controls could then be dynamically loaded into different areas of the page. Microsoft has released the sample IBuySpy application to illustrate this architecture. The IBuySpy application can be located at www.ibuyspy.com.

With this methodology in mind, you may be asking yourself what is the difference between ASP.NET user controls and simply embedding other pages on the page? Couldn’t we do that in ASP 3.0? The power comes from the framework treating the user controls as a standalone object. By exposing properties of the control through the code-behind (or in the HTML), other elements can interact with the user control programmatically and with ease. While replicating this functionality is possible in ASP 3.0, it was quite a troublesome task. Now with user controls being treated as objects, we can get and set values such as mode, size, behavior dictation, and colors with relative ease.

User Controls vs. Other Controls

One source of confusion when working with ASP.NET is knowing the difference between the many different types of controls out there and what they should be called. Microsoft has attempted to distinguish this variety, but myriad names still exist for elements that have only subtle differences. For instance, an ASP.NET control (sometimes called a server control) is a server-side component that is shipped with .NET Framework. A server control is a compiled DLL file and cannot be edited. It can, however, be manipulated through its public properties at design-time or runtime. It is possible to build a custom server control (sometimes called a custom control or composite control). (We will build these in part 2 of this article.)

In contrast, a user control will consist of previously built server controls (called constituent controls when used within a user control). It has an interface that can be completely edited and changed. It can be manipulated at design-time and runtime via properties that you are responsible for creating. While there will be a multitude of controls for every possible function built by third-party vendors for ASP.NET, they will exist in the form of compiled server controls, as mentioned above. Custom server controls may be the .NET answer to ActiveX Web controls.

Creating a Simple User Control

In this article, we will build two user controls. To cover the very basics, our first example will be an extremely simple calendar control. The control builds on the functionality of the existing ASP.NET calendar control by adding a text box to store the value selected. The calendar visibility will be toggled by a button. The user control could then be useful on a form that requires a date to be entered, but page real estate is a concern.

For clarity, both examples are written in C#, and the full source code is available below.

To create our first user control, we need to add a user-control file to a project. First, create a new C# ASP.NET Web application. Right click on the project in the Project Explorer and click Add – Add New Item and select a Web User Control item. This adds a file with the extension .ascx to the project. This is the file that the user control will use to expose its interface. An .ASCX file cannot be viewed directly in the browser. It will need to be placed within a container (such as another Web form) to be viewed. So, let’s add a new Web form to the project, open it, and drag the user-control file onto the page. The following is displayed.

An ASP.NET user control is placed on a Web form
Figure 1 – An ASP.NET user control is placed on a Web form here. User controls cannot be viewed directly. They must be placed within a host, such as a Web form, to be viewed.

Notice how the control does not show any interface in the designer. This can be a problem if your control takes up any amount of space. You will have to view it in the browser to see how it looks and to make adjustments to height and width. Also notice how the page represents the control as an object. If you look at the HTML by clicking on the HTML tab, you see the following.

The user control is placed on the hosting page like any server control
Figure 2 – The user control is placed on the hosting page like any server control, only its directive is explicitly declared.

The control is represented with tags on the page, much like a server control would be. Notice the “@ Register” directive on line 2. This registers the control on the page. Once the control is registered on the page, you can freely add many instances of the controls to the page. The “TagPrefix” attribute specifies the prefix to use for the control(s). It is sort of like a namespace in which several controls might share a single prefix value. This is why all ASP.NET server controls specify the “<asp:” prefix. The only difference is that the ASP.NET server control directive is implied and not explicitly declared. The TagName specifies the name of the control. Together, the tags create an instance of the control specified at the location of the “Src” attribute. You must also include the “runat=’server'” name/value pair to manipulate the user control programmatically. Otherwise, only the raw HTML is sent back to the browser.

Next, open the user-control file. It contains both an ascx file and an ascx.cs file. In the designer, drag and position a text-box server control, a button server control, and a calendar server control. As stated earlier, elements placed for use within a user control are called “constituent controls”. In the HTML view, format the constituent controls as follows.

The user-control ASCX file contains HTML and server controls
Figure 3 – The user-control ASCX file contains HTML and server controls.

Notice the lack of <BODY> tags. A user control does not need these tags because it will be placed on another page (or another user control) and rendered inline. The hosting page will be responsible for these common tags. The user control will, therefore, inherit all the host tags (including styles), unless they are specified otherwise. Finally, you can add code logic to the code-behind file (ascx.cs file) as appropriate.

This is some simple C# logic in the code-behind file
Figure 4 -This is some simple C# logic in the code-behind file.

The code in the code-behind works exactly the same as a Web form. HTML will be rendered and sent to the browser exactly as if the user control’s resulting HTML was simply pasted into the hosting page’s markup. In this code, we are catching a button click, and the page is posting back. If the user control is placed on a page and posts back to the server, the entire page is posted back. This control is screaming for some advanced functionality, such as the ability to not post back with each button click and the ability to do text-box validation. A makeover is also in order. While this control has much to be desired, it is a good starting point and a useful example of extending the capabilities of an existing control. Let’s look at a slightly more complex control, a login screen.

Creating a Slightly More Complex Control

For this example, we will create a login screen that consists of two labels, two text-box server controls, two required field-validation server controls, and a button server control. We will also expose a property or two to make it a little more versatile. After we have created a blank user control in our project, add the following.

This is thee HTML interface to the login control
Figure 5 – This is thee HTML interface to the login control. The red asterisks are required field-validation controls.

In the code-behind, add the following code.

This is the C# code in the code-behind
Figure 6 – This is the C# code in the code-behind.

The first thing to notice is that a user-control class is abstract. It must be inherited to implement its functionality. This is done by the parent page, which treats the user controls as a child object. Also, notice that the class inherits from System.Web.UI.UserControl. This gives the control the internal plumbing it needs to render itself. Most of the events and properties can be specified and overridden in your code-behind. After the control declarations, we declare two global variables. These contain the values set in the public property get and set routines. Also, be aware that the sBorderColor variable is public because we are referencing this variable in the HTML using our tried and true <% %> tags.

This demonstrates response writing the border color value into the STYLE section of the document
Figure 7 – This demonstrates response writing the border color value into the <STYLE> section of the document. Again, notice the lack of <BODY> tags.

The get and set routines
Figure 8 – The get and set routines provide a gateway to our private variables.

The get and set routines set the global variables’ values. The properties of the user control can either be set in the host page HTML at design-time or in the host page code-behind at runtime.

Properties are set inline with the HTML
Figure 9 – Properties are set inline with the HTML, just like ASP.NET server controls.

Notice how the property names exposed in the get and set routines are specified in the control declaration on the hosting page. Values can be passed in here as strings. As we will see in part 2, the internal logic may be expecting a different data type, and we will have to handle that circumstance. Also, the property names are not case-sensitive if referenced in the HTML. By setting some special attributes on the class, properties may also be set as child elements on the object. To do this, set the class attribute “ParseChildrenAttribute” equal to true. This may be useful if you have a multitude of properties to set or child controls to create at runtime. The DataGrid server control and calendar server control make good use of this.

This is the routine to set the username text-box value
Figure 10 – This is the routine to set the username text-box value.

Now we set the text-box equal to the sUsername value. The event that this fires on is the OnPreRender event. This event is part of the page life cycle (which user controls consequently share), and we are overriding it to fire our code at that time. The OnPreRender event is one of the last events that fires during the creation of a page, so we are assured that the contents of the text box will not be disturbed by typical mechanisms in the ASP.NET page life cycle. If we ran this code at the Page_Load event, the contents of our text box would not remain intact because the ViewState information would clear it out. For more information on the course of a page from creation to disposal, look at my article entitled The ASP.NET Page Life Cycle. By using this functionality, we can set the username text box if we need to, as described in the code comments above.

Setting the username property is not required at all, but it is important to thoroughly test your controls with various (or no) values set in your properties. You may get unexpected results. Placeholders are set within the code above to allow you to get the username from other sources, such as a cookie or previous login. When completed, the control could be placed on any page that requires a login. Logic could be placed in the Page_Load event that will set the control’s visibility property to false if the user has the required credentials. Since the control is seen as one complete object, this is done by simply making the statement, “this.visibility = false”.

Conclusion

While this control is also quite simple, it lays the foundation for much more complex and innovative user controls. User controls can be very useful for breaking down a large application into smaller, more manageable chunks. In part 2 of this article, we will dive into a much more complex compiled custom, server control. We will discuss some of the issues about making the control behave correctly and emit cross-browser HTML, and adding the control to the Integration Development Environment (IDE) toolbox. Finally, we will use both of these controls’ types together for some rather dramatic results.

Appreciation

I would like to thank my wife for her support through the years. I would also like to thank my colleague and friend, Joe Slovinski, for his continued help.

About the Author

Solomon Shaffer has worked in the information technology industry for more than five years. He recently founded Cynthetic, Inc., a software-development practice focused on .NET and Microsoft Internet technologies. Solomon’s areas of expertise include .NET, ASP, SQL Server, COM, and UI layout/design.

At press time, Solomon is working on a contract basis in the Atlanta area building the next-generation Web applications using the .NET platform. He has over one year of enterprise .NET development experience, developing enterprise applications with the platform since its Beta 1 release as part of the Early Adopters Program. Solomon and his wife reside in Alpharetta, Georgia.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read