Technologies: User Controls | Code-behind | Reflection
ASP.NET Makes Reusing Code Easy
By Doug Seven
ASP.NET and the .NET Framework introduce a new structure for building dynamic Web applications. In previous incarnations of ASP, developers became accustomed to working with server-side includes as a means of easy code reuse. They were the best thing available at the time, but using includes still came with problems:
- Includes were processed in the same space as the page they were on, so variable conflicts were frequent.
- An include file could be used only once on a page, so making controls that appeared multiple times on a page was cumbersome.
- Includes did not support an object model that allowed for exposing properties and methods.
Although ASP.NET does support the use of includes, it also introduces a new means of encapsulating code for reuse: the user control.
In this article, you will learn what a user control is, what its advantages are, and how to build and interact with it. You ll start with some basic examples and build on them until you have made a complex user control that exposes properties and methods.
What Is a User Control?
The .NET Framework SDK documentation defines a user control as a user-authored server control that enables an ASP.NET page to be reused as a server control. A few modifications can turn any ASP.NET Web Form into a user control you ll learn more about that later. For now, understand that in its simplest form, a user control is no more than text saved in a separate file and used on a Web Form like any server control.
User controls provide an easy means of writing reusable logic and user-interface code. You can write user controls in any text editor, as you can Web Forms. However, you must save user controls with the extension .ascx. The .NET Framework identifies them as user controls based on this extension. User controls are compiled the first time they are used and are saved in memory the same way Web Forms are. One of the great advantages user controls have over includes is that user controls support the ASP.NET object model, which means they can expose properties and methods like any other object in the .NET Framework. User controls are designed for use in a single Web application, and are not designed to port across application boundaries. For reusable components that encapsulate logic and UI and are for use in multiple applications, use custom server controls.
Building a Basic User Control
As I said before, a user control is, in its simplest form, just text saved in a separate file that you can use on any Web Form in your application. You cannot navigate to user controls independently because they are only accessible as controls on a Web Form. Because of this, user controls should never contain , , and elements. Those elements will be in the Web Form.
To build a simple user control, open your favorite text editor and create a new file named MyUserControl.ascx. In this file, type the text This is my user control and save the file. That s it. You have created a user control. To use it, register it on a Web Form, which will enable you to place it on the Web Form just like any ASP.NET server control. Create a new Web Form named WebForm1.aspx in the same directory as the user control and add the code from FIGURE 1.
<%@ Register TagPrefix="DotNetJunkies"
FIGURE 1: Registering a user control on a Web Form.
With this code, you register the user control on the Web Form using the @ Register directive. The three attributes of the @ Register directive are:
- TagPrefix The prefix used when placing the control on the Web Form, similar to how asp is used to prefix intrinsic server controls.
- TagName The name by which the control is referenced.
- Src The absolute or relative location of the user control.
want to place the user control on the page, use the syntax
As with any object in the .NET Framework, user controls can expose properties. Once a user control exposes a property, you can access it either declaratively or programmatically. Creating properties for a user control is the same as creating properties for any object. Properties can be created as Public instances of a variable, or as Property objects with Get and Set methods.
Change the MyUserControl.aspx file to include the following code:
With this code, you create a public string variable named Text. This variable is accessible outside the user control because you declared it publicly. The code uses the <%= %> Response.Write shortcut to write the value of the Text variable. In the Web Form, you can set the value of the Text variable declaratively, as follows:
Text="This is the Text
property." /> The resulting page is shown in FIGURE 2. One of
the advantages user controls have over include files is that user controls are
processed in their own sandboxes. In other words, each instance of a user
control is in an isolated processing space, which protects it from any variable
conflicts. This enables multiple instances of the same user control on one Web
Form, without any conflicts. Change WebForm1.aspx to use the code from FIGURE
3. <%@ Register
TagPrefix="DotNetJunkies" TagName="MyUserControl" SRC="MyUserControl.ascx" %>
FIGURE 2: The user control is rendered as an HTML element within the page.
Text="This is the Text property." />
The resulting page is shown in FIGURE 2.
One of the advantages user controls have over include files is that user controls are processed in their own sandboxes. In other words, each instance of a user control is in an isolated processing space, which protects it from any variable conflicts. This enables multiple instances of the same user control on one Web Form, without any conflicts. Change WebForm1.aspx to use the code from FIGURE 3.
<%@ Register TagPrefix="DotNetJunkies"
FIGURE 3: Using multiple instances of one user control.
In this Web Form, you use the same user control three times and provide a separate value for the Text property with each one. If you had tried to use the same include file three times in one ASP page, you would have raised the following error:
Microsoft VBScript compilation (0x800A0411)
Because each user control instance is processed in its own sandbox, no variable conflicts occur. Instead, you get the page shown in FIGURE 4.
FIGURE 4: Each user control instance is rendered appropriately, without conflicts.
Properties in user controls also can be exposed as Property objects with Get and Set methods. This allows for code execution to occur when a property is either set or read. Create a new user control named MyOtherUserControl.ascx and add the code shown in FIGURE 5.
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
FIGURE 6: Setting user control properties declaratively.
In the Web Form, register the user control and place two instances of it on the page. In each instance, you declaratively set the values of the two publicly exposed properties. Notice that if you attempt to set the _table variable from the Web Form, nothing will happen. This is because you declared the _table variable privately, and it is not accessible outside the user control.
When you request this Web Form in a browser, the two properties for the user controls are set, and the code in the Set method executes. See the resulting page, shown in FIGURE 7.
FIGURE 7: The user control properties determine the user control output.
Just as user controls can expose properties, they also can expose methods. By exposing a public method in the user control, you can achieve the same functionality the Table property managed in the previous user control. Create a new user control named MyThirdUserControl.ascx and add the code shown in FIGURE 8.
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
FIGURE 9: Programmatically invoking user control methods.
In WebForm3.aspx, you register the user control as in previous examples. When you place the user control on the page, you add an ID value to it so you can access it programmatically, like any control in ASP.NET. In the Page_Load event handler for the Web Form, you set the Text property of the user control by using the syntax:
ID.Property = Value
Next, you invoke the GetData method with the syntax:
The resulting page looks identical to the page you saw in FIGURE 7.
The Benefits of Code-behind
User controls can be tied to a code-behind class in the same way Web Forms can. This allows for a clean separation of code and content. When using code-behind with a Web Form, the code-behind class is defined in the Page directive. With user controls, the Control directive is used because a user control does not inherit from the System.Web.UI.Page class, but rather from the System.Web.UI.UserControl class. The attributes for the Control directive are the same as for the Page directive, with the exception of the Trace attribute which is not available in the Control directive. Tracing must be enabled at the page level, not the control level.
You can convert the user control MyThirdUserControl.ascx to use code-behind by making a few modifications. First, you must move all the programmatic code to a separate code-behind file named MyThirdUserControl.ascx.vb. (This follows the Visual Studio .NET naming convention.) The code for this file can be found in FIGURE 10.
Public Class MyThirdUserControl : Inherits UserControl
Protected TextLabel As Label
Protected myGrid As DataGrid
Public Property Text As String
TextLabel.Text = Value
Public Sub GetData(_table As String)
Dim SqlStmt As String = "SELECT TOP 2 * FROM " & _table
Dim conString As String = _
Dim con As SqlConnection = New _
Dim cmd As SqlCommand = New _
myGrid.DataSource = cmd.ExecuteReader()
FIGURE 10: Creating a user control with a code-behind class.
The user control code-behind class looks nearly identical to a Web Form code-behind class. The main difference is that the user control code-behind class inherits from System.Web.UI.UserControl rather than System.Web.UI.Page. The .ascx file is now stripped of all programmatic code, leaving only UI code. The Control directive is needed to tell the JIT compilers what code-behind class the user control inherits. And, if the code-behind class is not precompiled, you use the Src attribute to tell the JIT compiler where to find the class file:
<%@ Control Inherits="MyThirdUserControl"
FIGURE 12: Using multiple instances of one user control.
When you browse to the WebForm4.aspx, the resulting page is identical to that shown in FIGURE 7.
Using Precompiled User Controls and Known Classes
Using precompiled code-behind classes with user controls does not require the use of reflection because the user control s class type is known at compile time. Because the user control s type, properties, and methods also are known at compile time, they are directly accessible in the Web Form code-behind class, as shown in FIGURE 13.
Public Class WebForm5 : Inherits Page
Protected UC1 As CompiledUC
Protected UC2 As CompiledUC
Protected Sub Page_Load(Sender As Object, E As EventArgs)
UC1.Text = "This is the Customers Table"
UC2.Text = "This is the Products Table"
FIGURE 13: Setting precompiled user control properties programmatically from code-behind.
The code example in FIGURE 13 assumes the class name for the user control was changed from MyThirdUserControl to CompiledUC, and the user control s code-behind class was compiled into a DLL and placed in the application s \bin folder. Because the type CompiledUC is known when the Web Form is requested, the user control instances can be mapped directly to this class. As a result, the Text property and GetData method are known and can be called directly without using reflection.
User controls provide an easy means of writing reusable code and user interface elements. Like Web Forms, user controls can be created using any text editor. And, unlike custom server controls, they do not have to be compiled. In its simplest form, a user control is just text that may be reused in an application in many places. In more complex user controls, properties and methods may be exposed, and complex code execution can occur. User controls support the .NET object model, which allows for more power and flexibility than include files provide. Also, each user control is processed in its own sandbox, which prevents naming and variable conflicts when more than one instance of the user control appears in a single Web Form.
User controls are designed and intended for building reusable code modules whether logic only or logic and UI for use in a single Web application. When you need reusable code elements that can span application or machine boundaries, you should use custom server controls instead of user controls.
The files referenced in this article are available for download.
Doug Seven is a co-founder of the .NET training company DotNetJunkies.com. He came to DotNetJunkies.com by way of technical roles at Nordstrom, Microsoft, and GiftCertificates.com and a position as training specialist at Seattle Coffee Company. Seven co-authored Programming Data-Driven Web Applications with ASP.NET and ASP.NET: Tips, Tutorials, & Code, and is currently working on Professional ADO.NET and Building Custom Controls for ASP.NET. Readers may contact him at mailto:[email protected].
Tell us what you think! Please send any comments about this article to [email protected]. Please include the article title and author.