WHAT’S IN THIS CHAPTER?
WROX.COM CODE DOWNLOADS FOR THIS CHAPTER
Please note that all the code examples in this chapter are available as a part of this chapter’s code download on the book’s website at www.wrox.com on the Download Code tab.
As discussed in the previous chapter, ASP.NET evolved from Microsoft’s earlier web technology called Active Server Pages (referred to as ASP then and classic ASP today). This model was completely different from today’s ASP.NET. Classic ASP used interpreted languages to accomplish the construction of the final HTML document before it was sent to the browser. ASP.NET, on the other hand, uses true compiled languages to accomplish the same task. The idea of building web pages based on objects in a compiled environment is one of the main focuses of this chapter.
This chapter looks at how to use a particular type of object in ASP.NET pages called a server control and how you can profit from using this control. This chapter introduces a particular type of server control — the HTML server control. Then it demonstrates how you can use JavaScript in ASP.NET pages to modify the behavior of server controls.
The rest of this chapter shows you how to use and manipulate server controls, both visually and programmatically, to help with the creation of your ASP.NET pages.
In the past, one of the difficulties of working with classic ASP was that you were in charge of the entire HTML output from the browser by virtue of the server-side code you wrote. Although this might seem ideal, it created a problem because each browser interpreted the HTML given to it in a slightly different manner.
The two main browsers at the time were Microsoft’s Internet Explorer and Netscape Navigator. This meant that not only did developers have to be cognizant of the browser type to which they were outputting HTML, but they also had to take into account which versions of those particular browsers might be making a request to their application. Some developers resolved the issue by creating two separate applications. When an end user made an initial request to the application, the code made a browser check to see what browser type was making the request. Then, the ASP page would redirect the request down one path for an IE user or down another path for a Netscape user.
Because requests came from so many versions of the same browser, the developer often designed for the lowest possible version that might be used to visit the site. Essentially, everyone lost out by using the lowest common denominator as the target. This technique ensured that the page was rendered properly in most browsers making a request, but it also forced the developer to dumb-down the application. If applications were always built for the lowest common denominator, the developer could never take advantage of some of the more advanced features offered by newer browser versions.
ASP.NET server controls overcome these obstacles. When using the server controls provided by ASP.NET, you are not specifying the HTML to be output from your server-side code. Rather, you are specifying the functionality you want to see in the browser and letting ASP.NET decide on the output to be sent to the browser.
When a request comes in, ASP.NET examines the request to see which browser type is making the request, as well as the version of the browser, and then it produces HTML output specific to that browser. This process is accomplished by processing a User Agent header retrieved from the HTTP request to sniff the browser. This means that you can now build for the best browsers without worrying about whether features will work in the browsers making requests to your applications. Because of the previously described capabilities, you will often hear these controls referred to as smart controls.
ASP.NET provides two distinct types of server controls — HTML server controls and web server controls. Each type of control is quite different and, as you work with ASP.NET, you will see that much of the focus is on the web server controls. This does not mean that HTML server controls have no value. They do provide you with many capabilities — some that web server controls do not give you.
You might be asking yourself which is the better control type to use. The answer is that it really depends on what you are trying to achieve. HTML server controls map to specific HTML elements. You can place an HtmlTable server control on your ASP.NET page that works dynamically with a <table> element. On the other hand, web server controls map to specific functionality that you want on your ASP.NET pages. This means an <asp:Panel> control might use a <table> or another element altogether — it really depends on the capability of the browser making the request.
Table 4-1 provides a summary of information on when to use HTML server controls and when to use web server controls.
CONTROL TYPE | WHEN TO USE THIS CONTROL TYPE |
HTML Server | When converting traditional ASP 3.0 web pages to ASP.NET web pages and speed of completion is a concern. It is a lot easier to change your HTML elements to HTML server controls than it is to change them to web server controls. When you prefer a more HTML-type programming model. When you want to explicitly control the code that is generated for the browser. Using ASP.NET MVC for this (covered in Chapter 34) might be a better answer. |
Web Server | When you require a richer set of functionality to perform complicated page requirements. When you are developing web pages that will be viewed by a multitude of browser types and that require different code based upon these types. When you prefer a more Visual Basic–type programming model that is based on the use of controls and control properties. |
Of course, some developers like to separate certain controls from the rest and place them in their own categories. For instance, you may see references to the following types of controls:
When you are deciding between HTML server controls and web server controls, remember that no hard and fast rules exist about which type to use. You might find yourself working with one control type more than another, but certain features are available in one control type that might not be available in the other. If you are trying to accomplish a specific task and you do not see a solution with the control type you are using, look at the other control type because it may very well hold the answer. Also, realize that you can mix and match these control types. There are no barriers to using both HTML server controls and web server controls on the same page or within the same application.
You have a couple of ways to use server controls to construct your ASP.NET pages. You can actually use tools that are specifically designed to work with ASP.NET 4.5 that enable you to visually drag and drop controls onto a design surface and manipulate the behavior of the control. You can also work with server controls directly through code input.
Visual Studio 2012 enables you to visually create an ASP.NET page by dragging and dropping visual controls onto a design surface. You can get to this visual design option by clicking the Design tab at the bottom of the IDE when viewing your ASP.NET page. You can also show the Design view and the Source Code view in the same document window. This feature was introduced in Visual Studio 2008. When the Design view is present, you can place the cursor on the page in the location where you want the control to appear and then double-click the control you want in the Toolbox window of Visual Studio.
In the Design view of your page, you can highlight a control and the properties for the control appear in the Properties window. For example, Figure 4-1 shows a Button control selected in the Design panel and its properties are displayed in the Properties window on the lower right.
Changing the properties in the window changes the appearance or behavior of the highlighted control. Because all controls inherit from a specific base class (WebControl), you can also highlight multiple controls at the same time and change the base properties of all the controls at once. You do this by holding down the Ctrl key as you make your control selections.
You also can work from the code page directly. Because many developers prefer this, it is the default when you first create your ASP.NET page. Hand-coding your own ASP.NET pages may seem to be a slower approach than dragging and dropping controls onto a design surface, but it isn’t as slow as you might think. You get plenty of assistance in coding your applications from Visual Studio 2012. As you start typing in Visual Studio, the IntelliSense features kick in and help you with code auto-completion. Figure 4-2, for example, shows an IntelliSense drop-down list of possible code completion statements that appeared as the code was typed.
The IntelliSense focus is on the most commonly used attribute or statement for the control or piece of code that you are working with. Using IntelliSense effectively as you work is a great way to code with great speed.
As with Design view, the Source view of your page lets you drag and drop controls from the Toolbox onto the code page itself. For example, dragging and dropping a TextBox control onto the code page produces the same results as dropping it on the design page:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
You can also highlight a control in Source view or place your cursor in the code statement of the control, and the Properties window displays the properties of the control. Now, you can apply properties directly in the Properties window of Visual Studio, and these properties are dynamically added to the code of your control.
ASP.NET uses an event-driven model. Items or coding tasks are initiated only when a particular event occurs. A common event in the ASP.NET programming model is Page_Load, which is illustrated in Listing 4-1.
LISTING 4-1: Working with specific page events
VB
Protected Sub Page_Load(sender As Object, e As EventArgs)
'Insert code here
End Sub
C#
protected void Page_Load(Object sender, EventArgs e)
{
// Insert code here
}
Not only can you work with the overall page — as well as its properties and methods at particular moments in time through page events — but you can also work with the server controls contained on the page through particular control events. For example, one common event for a button on a form is Button_Click, which is illustrated in Listing 4-2.
LISTING 4-2: Working with a Button Click event
VB
Protected Sub Button1_Click(sender As Object, e As EventArgs)
'Insert code here
End Sub
C#
protected void Button1_Click(object sender, EventArgs e)
{
// Insert code here
}
The event shown in Listing 4-2 is fired only when the end user actually clicks the button on the form that has an OnClick attribute value of Button1_Click. Therefore, not only does the event handler exist in the server-side code of the ASP.NET page, but that handler is also hooked up using the OnClick property of the server control in the associated ASP.NET page markup, as illustrated in the following code:
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
How do you handle these events for server controls? You have a couple of ways to go about it. The first way is to pull up your ASP.NET page in the Design view and double-click the control for which you want to create a server-side event. For instance, double-clicking a Button server control in Design view creates the structure of the Button1_Click event within your server-side code, whether the code is in a code-behind file or inline. This creates a stub handler for that server control’s most popular event.
With that said, be aware that a considerable number of additional events are available to the Button control that you cannot get at by double-clicking the control. To access them, from any of the views within the IDE, choose the control from the Properties dialog box. Then you find a lightning bolt icon that provides you with a list of all the control’s events. From here, you can double-click the event you are interested in, and Visual Studio creates the stub of the function you need. Figure 4-3 shows the event list. You might, for example, want to work with the Button control’s PreRender event rather than its Click event. The handler for the event you choose is placed in your server-side code.
After you have an event structure in place, you can program specific actions that you want to occur when the event is fired.
More often than not, you want to change the default style (which is basically no style) to the server controls you implement in your applications. You most likely want to build your web applications so that they reflect your own look-and-feel. One way to customize the appearance of the controls in your pages is to change the controls’ properties.
As stated earlier in this chapter, to get at the properties of a particular control you highlight the control in the Design view of the page from Visual Studio. If you are working from the Source view, place the cursor in the code of the control. The properties presented in the Properties window allow you to control the appearance and behavior of the selected control.
Many of the default server controls that come with ASP.NET 4.5 are derived from the WebControl class and share similar properties that enable you to alter their appearance and behavior. Not all the derived controls use all the available properties (although many are implemented). Another important point is that not all server controls are implemented from the WebControl class. For instance, the Literal, PlaceHolder, Repeater, and XML server controls do not derive from the WebControl base class, but instead from the Control class.
HTML server controls also do not derive from the WebControl base class because they are more focused on the set attributes of particular HTML elements. Table 4-2 lists the common properties the server controls share.
PROPERTY | DESCRIPTION |
AccessKey | Enables you to assign a character to be associated with the Alt key so that the end user can activate the control using quick-keys on the keyboard. For instance, you can assign a Button control an AccessKey property value of K. Now, instead of clicking the button on the ASP.NET page (using a pointer controlled by the mouse), the end user can press Alt+K. |
Attributes | Enables you to define additional attributes for a web server control that are not defined by a public property. |
BackColor | Controls the color shown behind the control’s layout on the ASP.NET page. |
BorderColor | Assigns a color that is shown around the physical edge of the server control. |
BorderWidth | Assigns a value to the width of the line that makes up the border of the control. Placing a number as the value assigns the number as a pixel-width of the border. The default border color is black if the BorderColor property is not used in conjunction with the BorderWidth property setting. |
BorderStyle | Enables you to assign the design of the border that is placed around the server control. By default, the border is created as a straight line, but a number of different styles can be used for your borders. Other possible values for the BorderStyle property include Dotted, Dashed, Solid, Double, Groove, Ridge, Inset, None, NotSet, and Outset. |
ClientIDMode | Allows you to get or set the algorithm that is used to create the value of the ClientID property. |
CssClass | Assigns a custom CSS (Cascading Style Sheet) class to the control. |
Enabled | Enables you to turn off the functionality of the control by setting the value of this property to False. By default, the Enabled property is set to True. |
EnableTheming | Enables you to turn on theming capabilities for the selected server control. The default value is True. |
EnableViewState | Enables you to specify whether view state should be persisted for this control. |
Font | Sets the font for all the text that appears anywhere in the control. |
ForeColor | Sets the color of all the text that appears anywhere in the control. |
Height | Sets the height of the control. |
SkinID | Sets the skin to use when theming the control. |
Style | Enables you to apply CSS styles to the control. |
TabIndex | Sets the control’s tab position in the ASP.NET page. This property works in conjunction with other controls on the page. |
ToolTip | Assigns text that appears in a yellow box in the browser when a mouse pointer is held over the control for a short length of time. This can be used to add more instructions for the end user. |
Width | Sets the width of the control. |
You can see these common properties in many of the server controls you work with. Some of the properties of the WebControl class presented here work directly with the theming system built into ASP.NET such as the EnableTheming and SkinID properties. You also see additional properties that are specific to the control you are viewing. Learning about the properties from the preceding table enables you to quickly work with web server controls and to modify them to your needs.
In ASP.NET 3.5 and earlier, the rendered HTML from the ASP.NET server controls that you used weren’t always compliant with the latest HTML standards. As an example, in ASP.NET 3.5, you could set the Enabled property of the server control to False. This would render the control on the page but with a disabled attribute as illustrated here:
<span id="Label1" disabled="disabled">Hello there!</span>
This is not valid HTML as the span element does not have a disabled attribute.
In ASP.NET 4 and ASP.NET 4.5, the <pages> element within the web.config file instructs ASP.NET what version style to use when rendering controls. The default value is 4.0 as shown in the following code:
<pages controlRenderingCompatibilityVersion="4.0" />
If this value is set to 4.0, ASP.NET will disable the control using CSS correctly as shown here:
<span id="Label1" class="aspNetDisabled">Hello there!</span>
As you can see, ASP.NET sets the class attribute rather than the disabled attribute. To revert to the old way of control rendering, you can set the controlRenderingCompatibilityVersion value to 3.5.
ASP.NET enables you to take HTML elements and, with relatively little work on your part, turn them into server-side controls. Afterward, you can use them to control the behavior and actions of elements implemented in your ASP.NET pages.
Of course, you can place any HTML you want in your pages and you have the option of using the HTML as a server-side control. You can also find a list of HTML elements contained in the Toolbox of Visual Studio (shown in Figure 4-4).
Dragging and dropping any of these HTML elements from the Toolbox to the Design or Source view of your ASP.NET page in the Document window simply produces the appropriate HTML element. For instance, placing an HTML Button control on your page produces the following results in your code:
<input id="Button1" type="button" value="button" />
In this state, the Button control is not a server-side control. It is simply an HTML element and nothing more. You can turn this into an HTML server control very easily. In Source view, you change the HTML element by adding a runat="server" to the control:
<input id="Button1" type="button" value="button" runat="server" />
After the element is converted to a server control (through the addition of the runat="server" attribute and value), you can work with the selected element on the server side as you would work with any of the web server controls. Listing 4-3 shows an example of some HTML server controls.
LISTING 4-3: Working with HTML server controls
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Button1_ServerClick(sender As Object, e As EventArgs)
Response.Write(«Hello « & Text1.Value)
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Using HTML Server Controls</title>
</head>
<body>
<form id="form1" runat="server">
<div>
What is your name?<br />
<input id="Text1" type="text" runat="server" />
<input id="Button1" type="button" value="Submit" runat="server"
onserverclick="Button1_ServerClick" />
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Button1_ServerClick(object sender, EventArgs e)
{
Response.Write("Hello " + Text1.Value);
}
</script>
In this example, you can see two HTML server controls on the page. Both are typical HTML elements with the additional runat="server" attribute added. If you are working with HTML elements as server controls, you must include an id attribute so that the server control can be identified in the server-side code.
The Button control includes a reference to a server-side event using the OnServerClick attribute. This attribute points to the server-side event handler code that is executed when an end user clicks the button — in this case, Button1_ServerClick. Within the Button1_ServerClick method, the value placed in the textbox is output by using the Value property.
All the HTML server controls use a class that is derived from the HtmlControl base class (fully qualified as System.Web.UI.HtmlControls.HtmlControl). These classes expose many properties from the control’s derived class. Table 4-3 details some of the properties available from this base class. Some of these items are themselves derived from the base Control class.
METHOD OR PROPERTY | DESCRIPTION |
Attributes | Provides a collection of name/value pairs of all the available attributes specified in the control, including custom attributes. |
Disabled | Allows you to get or set whether the control is disabled using a Boolean value. |
EnableTheming | Enables you, using a Boolean value, to get or set whether the control takes part in the page-theming capabilities. |
EnableViewState | Allows you to get or set a Boolean value that indicates whether the control participates in the page’s view state capabilities. |
ID | Allows you to get or set the unique identifier for the control. |
Page | Allows you to get a reference to the Page object that contains the specified server control. |
Parent | Gets a reference to the parent control in the page control hierarchy. |
Site | Provides information about the container in which the server control belongs. |
SkinID | When the EnableTheming property is set to True, the SkinID property specifies the named skin that should be used in setting a theme. |
Style | Makes references to the CSS style collection that applies to the specified control. |
TagName | Provides the name of the element that is generated from the specified control. |
Visible | Specifies whether the control is visible (rendered) on the generated page. |
The HtmlControl base class is used for those HTML classes that are focused on HTML elements that can be contained within a single node. For instance, the <img>, <input>, and <link> elements work from classes derived from the HtmlControl class.
Other HTML elements, such as <a>, <form>, and <select>, require an opening and closing set of tags. These elements use classes that are derived from the HtmlContainerControl class, a class specifically designed to work with HTML elements that require a closing tag.
Because the HtmlContainerControl class is derived from the HtmlControl class, you have all the HtmlControl class’s properties and methods available to you as well as some new items that have been declared in the HtmlContainerControl class itself. The most important of these are the InnerText and InnerHtml properties:
It is quite possible to work with every HTML element because a corresponding class is available for each one of them. Table 4-4 contains a partial list of the server control classes that render HTML.
CLASS | HTML ELEMENT RENDERED |
HtmlAnchor | <a> |
HtmlArea | <area> |
HtmlAudio | <audio> |
HtmlButton | <button> |
HtmlForm | <form> |
HtmlHead | <head> |
HtmlIframe | <iframe> |
HtmlImage | <img> |
HtmlInputButton | <input type="button"> |
HtmlInputCheckBox | <input type="checkbox"> |
HtmlInputFile | <input type="file"> |
HtmlInputHidden | <input type="hidden"> |
HtmlInputImage | <input type="image"> |
HtmlInputPassword | <input type="password"> |
HtmlInputRadioButton | <input type="radio"> |
HtmlInputReset | <input type="reset"> |
HtmlInputSubmit | <input type="submit"> |
HtmlInputText | <input type="text"> |
HtmlLink | <link> |
HtmlMeta | <meta> |
HtmlSelect | <select> |
HtmlSource | <source> |
HtmlTable | <table> |
HtmlTableCell | <td> |
HtmlTableRow | <tr> |
HtmlTextArea | <textarea> |
HtmlTitle | <title> |
HtmlTrack | <track> |
HtmlVideo | <video> |
You gain access to one of these classes when you convert an HTML element to an HTML server control. For example, convert the <title> element to a server control this way:
<title id="Title1" runat="Server"/>
This gives you access to the HtmlTitle class for this particular HTML element. Using this class instance, you can perform a number of tasks including providing a text value for the page title dynamically:
VB
Title1.Text = DateTime.Now.ToString()
C#
Title1.Text = DateTime.Now.ToString();
You can get most of the HTML elements you need by using these classes, but a considerable number of other HTML elements are at your disposal that are not explicitly covered by one of these HTML classes. For example, the HtmlGenericControl class provides server-side access to any HTML element you want.
You should be aware of the importance of the HtmlGenericControl class; it gives you some capabilities that you do not get from any other server control offered by ASP.NET. For instance, using the HtmlGenericControl class, you can get server-side access to the <p>, <span>, or other elements that would otherwise be unreachable.
Listing 4-4 shows you how to change the new, HTML5 <progress> element in your page using the HtmlGenericControl class.
LISTING 4-4: Changing the <progress> element using the HtmlGenericControl class
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Page_Load(sender As Object, e As EventArgs)
Progress1.Attributes(«max") = 100
Progress1.Attributes(«value") = 25
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Using the HtmlGenericControl class</title>
</head>
<body>
<form id="form1" runat="server">
<progress id="Progress1" runat="server"></progress>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
Progress1.Attributes["max"] = "100";
Progress1.Attributes["value"] = "25";
}
</script>
In this example, the page’s <meta> element is turned into an HTML server control with the addition of the id and runat attributes. Because the HtmlGenericControl class (which inherits from HtmlControl) can work with a wide range of HTML elements, you cannot assign values to HTML attributes in the same manner as you do when working with the other HTML classes, such as HtmlInputButton. You assign values to the attributes of an HTML element using the HtmlGenericControl class’s Attributes property, specifying the attribute you are working with as a string value.
The following is a partial result of running the example page:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta id="Meta1" Name="description"
CONTENT="Generated on: 12/25/2012 2:42:52 AM"></meta>
<title>Using the HtmlGenericControl class</title>
</head>
By using the HtmlGenericControl class, along with the other HTML classes, you can manipulate every element of your ASP.NET pages from your server-side code.
When you create your ASP.NET pages with a series of controls, many of the controls are nested and many are even dynamically laid out by ASP.NET itself. For instance, when you are working with user controls, the GridView, ListView, Repeater, and more, ASP.NET is constructing a complicated control tree that is rendered to the page.
When this occurs, ASP.NET provides these dynamic controls with IDs. When it does, IDs such as GridView1$ctl02$ctl00 are generated. As with the controls, the IDs are dynamic. Because these IDs are unpredictable, the ID generation makes it difficult to work with the control from client-side code.
To help with this situation, ASP.NET 4.5 includes the ability to control the IDs that are used for your controls. To demonstrate the issue, Listing 4-5 shows some code that results in some unpredictable client IDs for the controls. To start, first create a user control.
LISTING 4-5: A user control with some simple controls
<%@ Control Language="C#" ClassName="Listing04_05" %>
<asp:TextBox ID="TextBox1" runat="server" />
<br />
<asp:Button ID="Button1" runat="server" Text="Button" />
Then the next step is to use this user control within one of your ASP.NET pages. This is illustrated in Listing 4-6.
LISTING 4-6: Making use of the user control within a simple ASP.NET page
<%@ Page Language="C#" Trace="true" %>
<%@ Register src="Listing04-05.ascx" tagname="MyUserControl" tagprefix="muc" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Working with Control IDs</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<muc:MyUserControl ID="MyUserControl1" runat="server" />
</div>
</form>
</body>
</html>
So this user control contains only two simple server controls that are then rendered onto the page. If you look back at Listing 4-5, you can see that they have pretty simple control IDs assigned to them. There is a TextBox server control with the ID value of TextBox1 and a Button server control with the ID value of Button1.
Looking at the page code from Listing 4-6, you can see in the @Page directive that the Trace attribute is set to True. This enables you to see the UniqueID that is produced in the control tree of the page. Running this page, you see the results in the page, as shown in Figure 4-5.
If you look at the source code for the page, you see the following snippet of code:
<div>
<input name="MyUserControl1$TextBox1" type="text" id="MyUserControl1_TextBox1" />
<br />
<input type="submit" name="MyUserControl1$Button1" value="Button"
id="MyUserControl1_Button1" />
</div>
From this, you can see that the ASP.NET assigned control IDs are lengthy and something you probably wouldn’t choose yourself. The TextBox server control was output with a name value of MyUserControl1$TextBox1 and an id value of MyUserControl1_TextBox1. A lot of this is done to make sure that the controls end up with a unique ID.
ASP.NET 4.5 includes the ability to control these assignments through the use of the ClientIDMode attribute. The possible values of this attribute include AutoID, Inherit, Predictable, and Static. An example of setting this value is provided here:
<muc:MyUserControl ID="MyUserControl1" runat="server" ClientIDMode="AutoID" />
This example uses AutoID, which forces the naming style to match the rules set in the .NET Framework 3.5 and earlier. Using this gives you the following results:
If you use Inherit, the same values would be populated as if you used AutoID. The reason is that it uses the containing control, the page, or the application in building the control. Therefore, for this example, you would end up with the same values as if you used AutoID. The Inherit value is the default value for all controls.
Predictable is generally used for data-bound controls that have a nesting of other controls (for example, the Repeater control). When used with a ClientIDRowSuffix property value, it appends this value rather than increments with a number (for example, ctrl1, ctrl2).
A value of Static gives you the name of the control you have assigned. It is up to you to ensure the uniqueness of the identifiers. Setting the ClientIDMode to Static for the user control in our example gives you the following values:
You can set the ClientID property at the control, container control, user control, page, or even application level via the <pages> element in the machine.config or Web.config file.
Now with this capability, you will find that working with your server controls using technologies like JavaScript on the client is far easier than before. The next section takes a look at using JavaScript within your ASP.NET pages.
Developers generally like to include some of their own custom JavaScript functions in their ASP.NET pages. You have a couple of ways to do this. The first is to apply JavaScript directly to the controls on your ASP.NET pages. For example, look at a simple TextBox server control, shown in Listing 4-7, which displays the current date and time.
LISTING 4-7: Showing the current date and time
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
TextBox1.Text = DateTime.Now.ToString()
End Sub
C#
protected void Page_Load(object sender, EventArgs e)
{
TextBox1.Text = DateTime.Now.ToString();
}
This little bit of code displays the current date and time on the page of the end user. The problem is that the date and time displayed are correct for the web server that generated the page. If someone sits in the Pacific time zone (PST) and the web server is in the Eastern time zone (EST), the page won’t be correct for that viewer. If you want the time to be correct for anyone visiting the site, regardless of where they reside in the world, you can employ JavaScript to work with the TextBox control, as illustrated in Listing 4-8.
LISTING 4-8: Using JavaScript to show the current time for the end user
<%@ Page Language="C#" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Using JavaScript</title>
</head>
<body onload="javascript:document.forms[0]['TextBox1'].value=Date();">
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" Runat="server" Width="300"></asp:TextBox>
</div>
</form>
</body>
</html>
In this example, even though you are using a standard TextBox server control from the web server control family, you can get at this control using JavaScript that is planted in the onload attribute of the <body> element. The value of the onload attribute actually points to the specific server control via an anonymous function by using the value of the ID attribute from the server control: TextBox1. You can get at other server controls on your page by employing the same methods. This bit of code produces the result illustrated in Figure 4-6.
ASP.NET uses the Page.ClientScript property to register and place JavaScript functions on your ASP.NET pages. Three of these methods are reviewed here. More methods and properties than just these three are available through the ClientScript object (which references an instance of System.Web.UI.ClientScriptManager), but these are the more useful ones. You can find the rest by searching the documentation online.
The RegisterClientScriptBlock method allows you to place a JavaScript function at the top of the page. This means that the script is in place for the startup of the page in the browser. Its use is illustrated in Listing 4-9.
LISTING 4-9: Using the RegisterClientScriptBlock method
VB
<%@ Page Language="VB" %>
<!DOCTYPE html>
<script runat="server">
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim myScript As String = "function AlertHello() {alert('Hello ASP.NET');}"
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "MyScript",
myScript, True)
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Adding JavaScript</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" Runat="server" Text="Button"
OnClientClick="AlertHello()" />
</div>
</form>
</body>
</html>
C#
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
string myScript = @"function AlertHello() { alert('Hello ASP.NET'); }";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
"MyScript", myScript, true);
}
</script>
From this example, you can see that you create the JavaScript function AlertHello() as a string called myScript. Then using the Page.ClientScript.RegisterClientScriptBlock method, you program the script to be placed on the page. The two possible constructions of the RegisterClientScriptBlock method are the following:
In the example from Listing 4-9, you are specifying the type as Me.GetType(), the key, the script to include, and then a Boolean value setting of True so that .NET places the script on the ASP.NET page with <script> tags automatically. When running the page, you can view the source code for the page to see the results:
<!DOCTYPE html
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>
Adding JavaScript
</title></head>
<body>
<form method="post" action="Listing04-09.aspx" id="form1">
<div class="aspNetHidden">
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="hbVKLJCpbcKtClOpVO6
+dE5HkSYJIxqrLCZF0BMbiZhhPdOepUjRfUukoZ7ZEg0BGQiZYBg8umPQQs/DvUX21ZQbhL3D4wLmJRxiVN
pCkLY=" />
</div>
<script type="text/javascript">
//<![CDATA[
function AlertHello() { alert('Hello ASP.NET'); }//]]>
</script>
<div class="aspNetHidden">
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="Sbe6uw
GDqPTxBfbGDMs1s8mWmBtO+sJwDh9YY6hS0PUZGqpOraDf1Mdrhkd3MgX5444UcMM5yv+j6yZi+XNuseFXe
9L9qv+l7YKNOLDHUJHJaibcCyLDb3qp0dOPcJkv" />
</div>
<div>
<input type="submit" name="Button1" value="Button" onclick="AlertHello();"
id="Button1" />
</div>
</form>
</body>
</html>
From this, you can see that the script specified was indeed included on the ASP.NET page before the relevant page code. Not only were the <script> tags included, but the proper comment tags were added around the script (so older browsers will not break).
The RegisterStartupScript method is not that different from the RegisterClientScriptBlock method. The big difference is that the RegisterStartupScript places the script at the bottom of the ASP.NET page instead of at the top. In fact, the RegisterStartupScript method even takes the same constructors as the RegisterClientScriptBlock method:
So what difference does it make where the script is registered on the page? A lot, actually!
If you have a bit of JavaScript that is working with one of the controls on your page, in most cases you want to use the RegisterStartupScript method instead of RegisterClientScriptBlock. For example, you use the following code to create a page that includes a simple <asp:TextBox> control that contains a default value of Hello ASP.NET:
<asp:TextBox ID="TextBox1" Runat="server">Hello ASP.NET</asp:TextBox>
Then use the RegisterClientScriptBlock method to place a script on the page that utilizes the value in the TextBox1 control, as illustrated in Listing 4-10.
LISTING 4-10: Improperly using the RegisterClientScriptBlock method
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim myScript As String = "alert(document.getElementById('TextBox1').value);"
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "myKey", myScript,
True)
End Sub
C#
protected void Page_Load(object sender, EventArgs e)
{
string myScript = @"alert(document.getElementById('TextBox1').value);";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
"MyScript", myScript, true);
}
Running this page (depending on the version of IE you are using) gives you a JavaScript error, as shown in Figure 4-7.
The reason for the error is that the JavaScript function fired before the textbox was placed on the screen. Therefore, the JavaScript function did not find TextBox1, and that caused an error to be thrown by the page. Now try the RegisterStartupScript method shown in Listing 4-11.
LISTING 4-11: Using the RegisterStartupScript method
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim myScript As String = "alert(document.forms[0]['TextBox1'].value);"
Page.ClientScript.RegisterStartupScript(Me.GetType(), "myKey", myScript,
True)
End Sub
C#
protected void Page_Load(object sender, EventArgs e)
{
string myScript = @"alert(document.forms[0]['TextBox1'].value);";
Page.ClientScript.RegisterStartupScript(this.GetType(),
"MyScript", myScript, true);
}
This approach puts the JavaScript function at the bottom of the ASP.NET page, so when the JavaScript starts, it finds the TextBox1 element and works as planned. The result is shown in Figure 4-8.
The final method is RegisterClientScriptInclude. Many developers place their JavaScript inside a .js file, which is considered a best practice because it makes it very easy to make global JavaScript changes to the application. You can register the script files on your ASP.NET pages using the RegisterClientScriptInclude method illustrated in Listing 4-12.
LISTING 4-12: Using the RegisterClientScriptInclude method
VB
Dim myScript As String = "myJavaScriptCode.js"
Page.ClientScript.RegisterClientScriptInclude("myKey", myScript)
C#
string myScript = "myJavaScriptCode.js";
Page.ClientScript.RegisterClientScriptInclude("myKey", myScript);
This creates the following construction on the ASP.NET page:
<script src="myJavaScriptCode.js" type="text/javascript"></script>
This chapter gave you one of the core building blocks of an ASP.NET page — the server control. The server control is an object-oriented approach to page development that encapsulates page elements into modifiable and expandable components. The chapter also looked at using HTML server controls and adding JavaScript to your pages to modify the behaviors of your controls.