LANGUAGES: VB.NET | SQL
ASP.NET VERSIONS: 1.0 | 1.1
Web Control Q&A
Everything You Ever Wanted to Know about Web Controls but Were Afraid to Ask
By Steve C. Orr
It's time to get everyone on the same page by answering some common questions about Web controls in ASP.NET.
Q: Why don't any controls show up on my page at run time?
A: A problem people often come across when setting up a machine for ASP.NET is that the controls don't show up on the page at run time. A common symptom is that Label values show up on the page, but other controls, such as Buttons and TextBoxes, do not. Most of the time the problem is that your IIS mappings aren't set. One way this can happen is by installing IIS after the .NET Framework has been installed. Luckily, this situation is easily remedied. To repair the mappings, simply run "aspnet_regiis.exe" with the "-i" command line parameter. This program can be found within the Windows directory under the Microsoft.NET\Framework\version folder. In other words, for a .NET 1.0 Web application, you'd likely need to run this from the command prompt:
For a .NET 1.1 Web application, the default path is:
Q: What exactly is a server control?
A: In short, a server control is any control that has the runat="server" attribute in the definition. The job of such a component is to render HTML to the output stream of a Web page. All server controls inherit directly or indirectly from System.Web.UI.Control. All the standard controls in the Web Forms tab of your Visual Studio.NET toolbox are server controls. This means that you can interact with them from the server-side code in the code-behind file of the page, manipulate properties of the control from code, call methods of the control, and respond to server-side events raised by the control.
A control dragged onto a form from the HTML tab of the Visual Studio.NET toolbox is not a server control by default, but can easily be turned it into one by right clicking on the control and selecting Run As Server Control. This action simply adds the runat="server" attribute to the control. Placing an HTML control on a page without the runat="server" attribute would render the control on the page at run time just the same as any control, but it could not be directly manipulated via server-side code. Performance benefits will be gained from not using a server control when a control doesn't need to be manipulated from server-side code, because that's one less control the server needs to instantiate.
Q: What's the difference between HTML controls and Web controls?
A: In the Visual Studio.NET toolbox there is a tab for HTML controls, and another tab for Web controls. Many of the controls found in the HTML tab have a similar, roughly equivalent, control in the Web controls tab. When an HTML control is dragged onto a Web form, it's represented in your ASPX with code such as this:
A Web control will look more like this:
HTML controls are quick and small and require little memory. Conversely, Web controls provide more advanced functionality than HTML controls.
You'll find the HTML controls to be intuitive and familiar if you're an old-school HTML Web developer. However, you're more likely to feel at home with the extra features that Web controls provide if you have more of a Windows/ActiveX development background. Why have two sets of similar controls? Microsoft didn't want to abandon developers with either background, so it made a set of controls for each. Freedom of choice is a wonderful thing.
Be aware that HTML controls were not designed to be especially extensible. Therefore, when making your own controls, you should instead inherit from WebControl or Control.
Q: What's the difference between user controls and custom controls?
A: There are two main categories of creatable Web controls. User controls are more simple to create, but custom controls are more simple to use. The extra effort that goes into creating custom controls pays off for the developer using the control at design time.
User controls are the natural evolution of include files, which are well known by old school ASP developers. If you're still using server-side include files in ASP.NET, it's time to leave them behind and dig into user controls, which are better in virtually every way. User controls are little more than a snippet of a Web page that can be dragged and dropped anywhere to duplicate bits of user interface and the associated functionality. (In fact, it's not difficult to convert an entire Web page into a user control.) They are object-oriented, so public properties can be added, as well as methods and events, to allow them to easily communicate with the page and other controls on the page.
User controls are saved with an ASCX file extension. Although they can be easily reused on any of the pages within the project in which they were created, there is no good way to reuse them in a different project. Another downside to user controls is that they only appear on the page at run time; at design time they appear on the page as an ugly gray box, making it difficult to envision how they'll appear to your users.
Figure 1 shows the HTML source code for a basic sidebar menu user control. A standard control like this is a navigational staple needed by virtually every page in a Web site. It would be wasteful to manually re-create such a structure over and over again for each page. Instead, simply drag this control from the Visual Studio.NET solution explorer window onto each page as needed. This example does not include any code-behind logic, but any user control can have a code-behind file of its own to contain any necessary server-side code. Figure 2 shows how the control looks on a Web page that includes a CSS style sheet to enhance the appearance.
<%@ Control Language="vb" AutoEventWireup="false" %>
Figure 1: A basic reusable side menu user control can be as simple as this. This control was created completely by dragging and dropping controls from the Visual Studio.NET toolbar onto an .ASCX user control page.
Figure 2: User controls are great for defining the layout for standard sections of Web pages. When combined with style sheets, they can morph to match the look and feel of any Web page on which they are hosted.
Custom controls can do everything that user controls can do - and much more. The biggest drawback is that they are more challenging and complex to create. Drag and drop is not supported for the creation of these controls. Therefore, all the HTML they output must be generated via code. In all the previous "Control Freak" columns, custom controls were used exclusively for every example. In addition to run-time functionality without limits, custom controls support rich design-time functionality. They can appear on a page at design time the same way they'll appear at run time, or differently if preferred. They can be adjusted to change how they'll appear in the toolbox, and how the properties will appear in the properties window. If the properties window doesn't support the desired functionality, it can be extended with custom popup dialog boxes and other UI tricks. Custom controls are easily distributed and can be enhanced with help documentation and licensing functionality, allowing them to be sold to other developers.
Q: How do I save the state of my controls between postbacks?
A: In many cases no action is required to save the state of controls between postbacks. When encapsulating existing controls within a user or custom control, they'll often save their own state just as they do when using them directly on Web pages. However, there are circumstances that will require custom data to be saved between postbacks. Imagine a simple control that contains only a LinkButton and a Label control. To save the number of times a user has clicked on the LinkButton and display that count in the Label control, a block of VB.NET code like this can be used in the code-behind:
Private Sub LinkButton1_Click(ByVal sender As Object,
ByVal e As EventArgs) Handles LinkButton1.Click
Dim i As Integer = CInt(ViewState("ClickCount"))
i = i + 1
ViewState("ClickCount") = i
Label1.Text = "Clicks: " & i.ToString
This code saves the custom data value in ViewState, indexed under the name "ClickCount". This code sample gets any existing value out of ViewState, increments it, then puts the new value back into ViewState. Finally, the value is displayed in the Label control. Because each control is automatically given a unique naming container within ViewState, control developers don't need to worry about naming collisions between multiple instances of a control on the same page. Figure 3 illustrates the fact that each instance of a control automatically has its own unique "ClickCount" ViewState value.
Figure 3: Each instance of a control automatically gets a unique ViewState, so you needn't be concerned with giving each instance of a control a unique ViewState name.
Q: How do I set the focus to a particular control on my page?
Perhaps it isn't known until run time which control should get the focus. In this case, code similar to the above example could be generated and output dynamically at run time via server-side code. For this, a subroutine like the one shown in Figure 4 could be used.
Private Sub SetFocus(ByVal ctrl As Control)
Dim sb As New System.Text.StringBuilder
Figure 4: This VB.NET code will set the initial focus to any control that is passed to it.
To call the method, simply execute a line of code such as this from the code-behind of a Web page:
Q: How do I send the output of a Web control via e-mail?
A: Assuming SMTP is configured properly on the server, the output of nearly any Web control can be captured via the output of its RenderControl method, and then sent out using the MailMessage class of the System.Web.Mail namespace. Such functionality is provided by the VB.NET method shown in Figure 5, which you can call from the code-behind class of any page.
Private Sub EmailControl(ByVal ctrl As Control,
ByVal ToEmailAddress As String)
' Get the output of the control.
Dim sb As New System.text.StringBuilder
Dim sw As New IO.StringWriter(sb)
Dim tw As New HtmlTextWriter(sw)
' Send the email.
Dim MailMsg As New Web.Mail.MailMessage
Dim svr As Web.Mail.SmtpMail
svr.SmtpServer = "smtp.mydomain.com"
MailMsg.To = ToEmailAddress
MailMsg.From = "[email protected]"
MailMsg.BodyFormat = Mail.MailFormat.Html
MailMsg.Subject = "Test Email"
MailMsg.Body = sb.ToString
Figure 5: This code will grab the HTML output of a control and send it to the specified e-mail address.
This code works well primarily for read-only controls, such as Labels, DataGrids, LinkButtons, etc. Editable controls such as TextBoxes don't tend to work as well because they expect to be hosted inside a form.
Of course, any network administrator will tell you that e-mail is a complex topic involving firewalls, spam filtering systems, and more. Therefore, there are plenty of ways the code in Figure 5 could fail, so (as always) you should employ error handling of one kind or another.
Do you have a question about Web controls that wasn't answered in this article? Send it to mailto:[email protected] and perhaps it will be published (along with the answer!) in a future article.
Steve C. Orr is an MCSD and a Microsoft MVP in ASP.NET. He's an independent consultant who develops software solutions for many leading companies in the Seattle area. When he's not busy designing software systems or writing about it, he can often be found loitering at local user groups and habitually lurking in the ASP.NET newsgroup. Find out more about him at http://Steve.Orr.net or e-mail him at mailto:[email protected].