Application Security Testing: An Integral Part of DevOps
by John Peterson
Server controls are one of the things that make developing with ASP.NET so simple and powerful at the same time. We've discussed HTML and web server controls and have showed you how to use them in your ASP.NET pages, but what if there's not a control that does exactly what you want to do?
Like most everything in ASP.NET there's really no magic involved with server controls. In fact, you can build your own controls and use them on your pages just like you use the ones that ship with .NET. Controls that you build are called user controls and they are the topic of this lesson.
Writing Your First User Control
I know how to use a server control, but writing one's got to be hard.
Actually, writing a basic user control (also sometimes called pagelets) couldn't be much easier... most any ASP.NET page can be used as a server control. Here's a simple example:
<p> This is a user control... really! </p>
That's it. Looking at that, I know you're probably thinking that I'm either drunk or half-asleep, but I'm really not (or am I?)... the above can easily be used as a user control. Granted it doesn't do that much, but it's great for illustrating that these things are really only as complicated as you make them. Notice the .ascx extension... it's the customary extension given to pages meant to be used as a control. It's not really anything special, but it does keep things easier to understand and by default .ascx files are prevented from being directly executed and served by IIS.
Now that we've created our user control, here's a sample of how to use it in an ASP.NET web page.
<%@ Page Language="VB" %> <%@ Register TagPrefix="asp101samps" TagName="SomeText" Src="basic.ascx" %> <html> <head> <title>ASP.NET User Control Sample - Basic</title> </head> <body bgcolor="#FFFFFF"> <asp101samps:SomeText runat="server" /> </body> </html>
The above page will output a standard HTML page with the text contained in our user control in place of the user control's tag. How does it do it? The magic here is in the Register directive. To use it you'll need to specify three attributes:
- The TagPrefix attribute defines a namespace in which the control will live. You can think of this as the world in which the control will live. Because of this, you can have different controls with the same name and as long as they have a different TagPrefix (and as a result different namespaces) they can peacefully co-exist on the same page.
- The TagName attribute determines the name by which the control will be refered to. It needs to be unique within the namespace, but you can choose whatever you like. Generally names are choosen that are indicative of what the control actually does.
- The Src (or source) attribute simply specifies where the code that makes up the control being defined is to be found. Vitual paths are used so the value should be something like "control.ascx" or "/path/control.ascx" and not a physical path like "C:\path\control.ascx."
Once you've added the Register directive, the control is registered and can be used
just like any other server control. You specify the TagPrefix and TagName in the
control's tag just like you would with a built in control and make sure you've got the
runat="server" attribute and you're ready to roll. Here's the
basic form for a user control's tag:
<TagPrefix:TagName runat="server" />
Giving Your Control Properties
That's great, but I could've just typed that text into the web page and it would've been faster and easier.
If that's all controls could do they would've been called include files! Thank goodness it doesn't stop there. I'm going to continue to use our stupidly simple example to keep things simple, but we are going to take it up a notch. This time around I've added two properties to the control - one to control the color and one to control the text.
<script language="VB" runat="server"> Public Color As String = "black" Public Text As String = "This is a user control... really!" </script> <p> <font color="<%= Color %>"> <%= Text %> </font> </p>
By default the control will look the same as before, but now we can modify the color or text it emits either by setting properties in the control's tag or programmatically from our code (as long as we give the control an id attribute by which to reference it). Also note that I'm able to reuse the same control a number of times in the page and set the properties of each instance indepedently.
<%@ Page Language="VB" %> <%@ Register TagPrefix="asp101samps" TagName="SomeText" Src="properties.ascx" %> <script language="VB" runat="server"> Sub Page_Load(Sender As Object, E As EventArgs) UserCtrl1.Color = "green" UserCtrl1.Text = "This control's properties were " _ & "set programmatically!" End Sub </script> <html> <head> <title>ASP.NET User Control Sample - Properties</title> </head> <body bgcolor="#FFFFFF"> <asp101samps:SomeText runat="server" /> <asp101samps:SomeText Color="red" runat="server" /> <asp101samps:SomeText Text="This is quite cool!" runat="server" /> <asp101samps:SomeText Color="blue" Text="Ain't It?" runat="server" /> <asp101samps:SomeText id="UserCtrl1" runat="server" /> </body> </html>
Having Your Control Handle Events
That's better, but how much more can we get them to do for us?
You can get your control to do almost anything you want it to. In the next set of code listings the control will handle the Page_Load event all by itself. This type of event handling allows you to write controls that need very little if any maintaining-code to be written in the page hosting the control. The controls can handle all their own events.
In addition, this control encapsulates a asp textbox control. I've even hooked our control's name property up to the text property of the textbox.
<script language="VB" runat="server"> Sub Page_Load(Src As Object, E As EventArgs) Dim strInitialText As String = "Please Enter a Name!" If Page.IsPostBack Then If txtName.Text = strInitialText txtName.Text = "" End If Else txtName.Text = strInitialText End If End Sub Public Property Name As String Get Return txtName.Text End Get Set txtName.Text = Value End Set End Property </script> Name: <asp:textbox id="txtName" runat="server" /> <asp:RequiredFieldValidator ControlToValidate="txtName" id="valtxtName" Display="Dynamic" runat=server> Please Enter a Name! </asp:RequiredFieldValidator>
<%@ Page Language="VB" ClientTarget="downlevel" %> <%@ Register TagPrefix="asp101samps" TagName="SomeText" Src="properties.ascx" %> <%@ Register TagPrefix="asp101samps" TagName="TextBox" Src="events.ascx" %> <script language="VB" runat="server"> Sub Page_Load(Sender As Object, E As EventArgs) txtLabel.Text = "" ' The textbox control handles it's own stuff ' in it's own Page_Load event handler. End Sub Sub btnSubmit_Click(Sender As Object, E As EventArgs) ' Sets the label to the textbox's text txtLabel.Text = txtName.Name ' I don't need to worry about validation since ' my user control does it for me. End Sub </script> <html> <head> <title>ASP.NET User Control Sample - Validation & Events</title> </head> <body bgcolor="#FFFFFF"> <form runat="server"> <asp101samps:TextBox id="txtName" runat="server" /> <br /> <asp:button id="btnSubmit" onClick="btnSubmit_Click" text="Submit" runat="server" /> </form> <asp101samps:SomeText id="txtLabel" runat="server" /> </body> </html>
In the example above I used the property syntax for defining and modifying the properties of our user control. I could have used this syntax for the earlier samples as well but I wasn't doing anything that required it. The property style of doing this allows you to execute commands upon setting or retreiving of the property, but it's a little more confusing and doesn't really gain you anything with simple properties which don't require any execution when modified.
That's About It
That should give you enough info to get started creating your own user controls. They can be as simple or as complex as you want, but they really do make reusability much easier then it ever was in classic ASP.
You can download the code from this article below.