Programming Microsoft Web Forms (Pro Developer)

 

Mixing Client and Server Code

Now we know that we cannot just call the MessageBox.Show method on the server in our .NET code. How can we do things like show a message box on the machine where the user is browsing (the client machine)? The answer lies in executing code on the client. Ideally, we could use the same programming environment and language to develop client and server code. Sadly, that is not an option.

To run on the client machine, code must operate in the browser. Currently, the only language supported by virtually all major browsers is JavaScript (the Microsoft implementation is known as JScript). Support runs all the way from Internet Explorer on my desktop machine down to Pocket Internet Explorer on my Pocket PC Phone Edition.

Unfortunately, using JavaScript on a Web Form is not as straightforward as using C# in Visual Basic .NET on the server. The client code must be placed appropriately in the HTML, and it cannot be called directly by server code. For example, a button click event can be captured in an HTML form by using code like this.

<input type="submit" OnClick="HandleClick()">

The HTML input tag can represent several different widgets on the screen. When the type is "submit", the browser renders the tag as a button, and when the button is clicked the form is submitted.

The OnClick attribute of the input tag calls the JavaScript function HandleClick. JavaScript is a very large language, one that has been the subject of numerous books. One of the most common functions in JavaScript is alert, which displays a simple message box. The alert function accepts a single argument, a string that is displayed in a message box. The exact look of the message box is dependent on the operating system on which the browser is running.

On the HTML side, the client event handler is identified by the OnClick attribute in the Input tag. Unfortunately, in the ASP.NET markup, the OnClick attribute on the ASP.NET Web controls is already used to identify the server-side event handler. To accommodate this, when you assign a client-side OnClick event handler, you must identify it with the OnClientClick attribute.

You can see how the alert function is used in Listing 1-1, which presents the markup for a page (Confirm.aspx) that displays a screen showing the text that the user entered.

Listing 1-1: HTML Source from Confirm.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Confirm.aspx.cs" Inherits="Confirm" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Confirm</title> <script language=javascript> <!-- function Test(what) { if ( what.TextBox1.value=='' ) { alert('You Entered: NOTHING!'); } else { alert('You Entered: ' + what.TextBox1.value); } } //--></script> </head> <body> <form runat="server"> <div> <asp:Label runat="server" Text="Label"></asp:Label> <br /> <asp:TextBox runat="server"></asp:TextBox><br /> <asp:Button runat="server" Text="Button" OnClientClick="Test(this.form)" OnClick="Button1_Click"/></div> </form> </body> </html>

A few elements of this page require some explanation. First, the <head> section of the page contains a script block. The script block contains a function (named Test in this case) that accepts a single parameter, which it expects to be a form although JavaScript is not strongly typed and will allow you to pass any value. The function verifies whether anything has been entered and echoes the entered text or, if nothing is entered, displays a message box that says, "You Entered: NOTHING!" The <!-- and //--> at the beginning and end of the script block are there to ensure that the page is parsed correctly.

This is a very simple page, but ASP.NET pages can be much more complex. Rather than using just text boxes and buttons, some ASP.NET pages use very complex controls that can actually contain other controls. The Wizard control will be covered completely in Chapter 3; for now, you only need to know that it is a container control for additional controls.

When you add a Wizard control to a page, and then add a text box to one of the steps of the wizard, you end up with a Web Form that looks like the one shown in Figure 1-11.

Figure 1-11: A Web Form with a wizard that includes a text box

When you run the Web Form shown in Figure 1-11, the source for the page (which can be viewed in Internet Explorer) is as shown in Listing 1-2.

Listing 1-2: HTML Source from WizardSample.aspx

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head><title> Untitled Page </title></head> <body> <form method="post" action="WizardSample.aspx" > <div> <input type="hidden" name="__EVENTTARGET" value="" /> <input type="hidden" name="__EVENTARGUMENT" value="" /> <input type="hidden" name="__VIEWSTATE" value="/wEPDwULLTE4ODY2MTUxNzZkGAQFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYIBT9XaX phcmQxJFN0YXJ0TmF2aWdhdGlvblRlbXBsYXRlQ29udGFpbmVySUQkU3RhcnROZXh0SW1hZ2VCdXR0b24FPFdpem FyZDEkU3RhcnROYXZpZ2F0aW9uVGVtcGxhdGVDb250YWluZXJJRCRDYW5jZWxJbWFnZUJ1dHRvbgVFV2l6YXJkMS RGaW5pc2hOYXZpZ2F0aW9uVGVtcGxhdGVDb250YWluZXJJRCRGaW5pc2hQcmV2aW91c0ltYWdlQnV0dG9uBT1XaX phcmQxJEZpbmlzaE5hdmlnYXRpb25UZW1wbGF0ZUNvbnRhaW5lcklEJEZpbmlzaEltYWdlQnV0dG9uBT1XaXphcm QxJEZpbmlzaE5hdmlnYXRpb25UZW1wbGF0ZUNvbnRhaW5lcklEJENhbmNlbEltYWdlQnV0dG9uBUFXaXphcmQxJF N0ZXBOYXZpZ2F0aW9uVGVtcGxhdGVDb250YWluZXJJRCRTdGVwUHJldmlvdXNJbWFnZUJ1dHRvbgU9V2l6YXJkMS RTdGVwTmF2aWdhdGlvblRlbXBsYXRlQ29udGFpbmVySUQkU3RlcE5leHRJbWFnZUJ1dHRvbgU7V2l6YXJkMSRTdG VwTmF2aWdhdGlvblRlbXBsYXRlQ29udGFpbmVySUQkQ2FuY2VsSW1hZ2VCdXR0b24FB1dpemFyZDEPEGQUKwABZm ZkBRdXaXphcmQxJFdpemFyZE11bHRpVmlldw8PZGZkBSRXaXphcmQxJFNpZGVCYXJDb250YWluZXIkU2lkZUJhck xpc3QPEGRkZmQLciREcHz1hDO82HgrQZUD6P3FOw==" /> </div> <script type="text/javascript"> <!-- var theForm = document.forms['form1']; if (!theForm) { theForm = document.form1; } function __doPostBack(eventTarget, eventArgument) { if (!theForm.onsubmit || (theForm.onsubmit() != false)) { theForm.__EVENTTARGET.value = eventTarget; theForm.__EVENTARGUMENT.value = eventArgument; theForm.submit(); } } // --> </script> <div> <table cellspacing="0" cellpadding="0" border="0" > <tr> <td ><a href="#Wizard1_SkipLink"><img alt="Skip Navigation Links." height="0" width="0" src="/books/4/401/1/html/2//SampleWebApplication/ WebResource.axd?d=2DwIkOCGwqRaTpfx8kmSBQ2&amp;t=632519130927750990" /></a> <table cellspacing="0" border="0" > <tr> <td > <a href="javascript:__doPostBack ('Wizard1$SideBarContainer$SideBarList$ctl00$SideBarButton','')"> Step 1</a></td></tr> <tr> <td><a href="javascript:__doPostBack ('Wizard1$SideBarContainer$SideBarList$ctl01$SideBarButton','')"> Step 2</a></td></tr> </table> <a ></a> </td> <td > <table cellspacing="0" cellpadding="0" border="0" > <tr > <td> <input name="Wizard1$TextBox1" type="text" /> </td></tr> <tr> <td align="right"> <table cellspacing="5" cellpadding="5" border="0"> <tr> <td align="right"><input type="submit" name="Wizard1$StartNavigationTemplateContainerID$StartNextButton" value="Next" /> </td></tr> </table> </td></tr> </table> </td></tr> </table> </div> </form> </body> </html>

Because this is a more complex form, the resulting HTML is much more complex. An interesting aspect of the HTML source is the size of the view state, stored in the hidden HTML input tag named __VIEWSTATE. It's huge! Recall that this is a Web Form with a single Wizard control, and that one step of the Wizard control contains a single text box. Some other controls make even greater use of view state. The size of view state can become a limiting factor for some applications. The content of the __VIEWSTATE input tag must be encoded on the server, transmitted to the client, resubmitted to the server, and decoded there. Between the load on the server and the burden on the network connection (which for many Internet sites includes several dial-up users) minimizing view state is an important goal.

Another interesting aspect of the page is the JavaScript toward the top. The function __doPostBack is included with any page that can cause a postback in a way other than a standard submit button, which includes just about any ASP.NET Web Form. Just above the __doPostBack function is an interesting bit of code that requires some explanation.

var theForm = document.forms['form1']; if (!theForm) { theForm = document.form1; }

The __doPostBack function needs the variable named theForm, and this code sets it. Then, if the variable has not been set properly, the code sets it in another way that will work for browsers that do not understand the first way. The Internet has a history of both standards and lack of standards. Although HTML is standardized, the internal object models inside browsers are not. The preceding code should allow the variable theForm to be set properly for most modern browsers.

One more interesting aspect of this page (and the reason I am showing it) is the way in which the name of the text box appears in the resulting HTML. The control is clearly named TextBox1 in the .aspx page, but it appears as follows in the resulting HTML.

<input name="Wizard1$TextBox1" type="text" />

Note that the name of the control in the HTML is Wizard1$TextBox1, and the ID is Wizard1_TextBox1. Why does ASP.NET change the ID you specified in the ASP.NET markup, TextBox1, to Wizard1_TextBox1? Imagine not a Wizard control, but rather a user control (a control that you can create yourself, which will be covered in Chapter 6, "Custom Controls"). Suppose that you placed multiple copies of that user control on a single form. If ASP.NET did not create a unique client ID, the page would not work in the browser. Adding the prefix Wizard1 plus another special character (depending on whether the name or the ID is being modified) is called fully qualifying the identifier. If the JavaScript for the Test function from Listing 1-1 were used here, it would not work, because the name of the text box is fully qualified.

Fortunately, there is a way to get the ID rendered on the client for any Web control. All Web controls expose a property named ClientID. Whenever you create JavaScript for use on a Web Form, it is critical that you use the ClientID property when accessing specific controls, rather than the ID you assign to the Web control on your .aspx page.

 

Категории