![]() |
< Day Day Up > |
![]() |
16.1. Client-Server Interaction over the InternetAt its core, the Internet consists of resources and users who want to access Web-based resources. Three mechanisms are required to enable this access: a naming scheme (URI) to locate the resources, a protocol (HTTP) defining how the request/response process works, and a language (HTML) for publishing information and providing a means to navigate to the resources. This environment is quite different than that facing the Windows Forms programmer and presents the Web application developer with three major challenges:
One of the best ways to understand and appreciate a technology is to compare it with other technologies that perform a similar task. With that in mind, this section takes a simple Web application and implements it in JavaScript, ASP, and ASP.NET. The objectives are twofold: to understand the problems associated with implementing a Web Forms application, and to illustrate the evolutionary approach that ASP.NET uses to meet these challenges. You do not need experience with ASP or JavaScript to understand the examples, but it helps. Their function is to demonstrate how the HTTP GET and POST methods send data to a server and maintain state information. The examples could just as easily use Perl or PHP scripting. Web Application Example: Implementing a BMI CalculatorThis application calculates the Body Mass Index (BMI) for a given height and weight. The user enters this information (see Figure 16-2) into a form and then clicks Submit Form to send the request to a server. The server calculates the BMI and returns a Web page that includes the BMI and original data entered. Figure 16-2. BMI Web calculatorRealistically, the calculation could be done using JavaScript on the client's page without requiring a trip to the server. But let's suppose that we also want to record each time the calculator is used. For that, a trip to the server is necessary. A JavaScript BMI CalculatorJavaScript remains the primary language used for client-side coding on a Web application. It is platform and browser independent (although there are a few exceptions). As we will see later, ASP.NET automatically generates JavaScript for its client-side processing. The first example uses JavaScript on both the client and server side. Listing 16-1 contains the HTML and JavaScript that comprise the client-side page. For brevity, some of the less important code is excluded. The HTML in the <body> defines the fields and buttons on a form bmi_input. This form defines GET as the HTML method for delivering the contents of the form to the server. When the button is clicked, control passes to the JavaScript function post that verifies the content of the form and sends it to the server. We'll get to the other JavaScript code after we look at the server side. Listing 16-1. JavaScript/HTML to Display a BMI Calculator?bmi.htm<HTML> <HEAD><TITLE>BMI Calculator</TITLE> <SCRIPT LANGUAGE="Javascript" TYPE="text/javascript"> <!? // hrefstr is set to querystring values梚f any var hrefstr= location.search.substring(1, location.search.length); function showbmi(){ if (hrefstr ) // display values in form fields { var parms = hrefstr.split('&'); var f = self.document.forms[0]; f.bmi.value = eval(parms[0]); f.hti.value = eval(parms[2]); f.wt.value = eval(parms[3]); f.htf.value = eval(parms[1]); } } // -->Code for Verify goes here. // Post Form to Web Host function post() { if (verify()) //Call function to verify values in form fields { var f = self.document.forms[0]; f.bmi.value=0; f.submit(); // Use HTTP GET to send form to server } } //--> </script> </HEAD> <BODY bgcolor=#ffffff> <FORM NAME="bmi_input" method=GET action=bmicalculator.htm> <table border=0 cellpadding=2 cellspacing=0 width=180 bgcolor=#cccccc> <tr><td colspan=3 align=center><font size=2 color=#33333> <b>BMI Calculator</b> </td></tr> <tr><td><font size=2 ><b>BMI:</b></td> <td colspan=2 ><input type=text size=5 name=bmi> </td></tr> <tr><td colspan=3><hr size=1></td></tr> <tr><td><font size=2 >Height:</td> <td><input type=text size=3 name=htf maxlength=1></td> <td><input type=text size=3 name=hti maxlength=2></td> </tr> <tr><td> </td><td valign=top><font size=2>feet</td> <td valign=top><font size=2>inches</td> </tr> <tr><td><font size=2 >Weight:</td> <td colspan=2><input type=text size=3 name=wt maxlength=3></td> </tr> <tr><td colspan=3 align=center> <INPUT TYPE="button" VALUE="Submit Form" ONCLICK= "self.post()";> </td></tr> <tr><td colspan=3> </td></tr> </table> </FORM> <SCRIPT LANGUAGE="Javascript" TYPE="text/javascript"> <!-- showbmi(); // Fills form with values if they exist //--> </script> </body> </html> Using the GET method causes the form's data to be sent to the server as part of the URL. This string of data, referred to as a query string, contains name-value pairs that correspond to the name of the fields on the form, followed by their value. Figure 16-3 shows how form data is passed to the Web page bmicalculator.htm that calculates the BMI. Figure 16-3. Passing data in a query stringData is returned to the client in the same manner梑y appending it to the URL of the page containing the original form. Note that bmi is now set to the calculated value. Here is the server-side code that creates this response: <html><head></head> <body > <script language="javascript"> <!? // Use location.search to access the query string var hrefstr = location.search.substring(1, location.search.length); var parms = hrefstr.split('&'); feet = parms[1]; inch = parms[2]; pounds = parms[3]; totinches = eval(feet)*12 + eval(inch); // ..... Calculate BMI var h2 = totinches * totinches; bmi = Math.round(eval(pounds) * 703 * 10/ h2)/10; // --> Place code here to maintain count of visits. //... Return value and original parameters as a query string ndx = hrefstr.indexOf('htf'); self.location = 'bmi.htm?bmi= '+bmi+"&"+hrefstr.substring(ndx); //--> </script> </body></html> This code grabs the values from the query string using location.search, parses them, calculates the BMI, and then creates a URL for the page to be returned. The final step is for the client browser to display the calculated BMI value. At the bottom of the code in Listing 16-1 is a call to the JavaScript function showbmi(). This function operates much like the preceding server code. It extracts the data from the query string and displays it in the appropriate fields on the form. Note that the function first confirms that the query string is not empty, as will be the case the first time the form is loaded. The use of a query string is popular for applications that transfer small amounts of data. However, it becomes a problem with large forms because the query string is limited by the 2K maximum string length imposed by some browsers (IE). In addition, it raises obvious security concerns by exposing data in a URL line that can be altered by the user. Query string encryption can mitigate this problem and should be considered where it makes sense. A more robust solution is to use the HTTP POST method in place of GET. An ASP (Active Server Pages) BMI CalculatorJavaScript is intended primarily for client-side scripting and cannot process data sent by a POST method. This example replaces the JavaScript server code with an ASP file that handles the POST request. We change one statement in the client code to indicate that POST is being used and to provide the name of the ASP server page: <FORM NAME="bmi_input" method=POST action=bmicalculator.asp> The code for the ASP server file is quite simple. It accesses the data passed from the client by referencing a request object. The data is passed to a VBScript function that calculates the BMI. A URL is then constructed that contains the query string with the BMI value and other parameters. The response.redirect method sends the form to the client's browser. <script language="VBScript" runat="server"> function getBMI(inch,feet,pounds) totinches = feet*12 + inch h2 = totinches * totinches getBMI= (pounds * 703 * 10/ h2)/10 end function </script> <% ' ... POST data is available in request object inch = request("hti") feet = request("htf") pounds = request("wt") bmi= left(cstr(getBMI(inch,feet,pounds)),4) ' ... return value and original parameters as a query string hrefstr = "&htf=" +cstr(feet) + "&hti=" + cstr(inch) + "&wt="&cstr(pounds) response.redirect ("bmi3.htm?bmi="+bmi+hrefstr) %> This solution illustrates the fundamental ASP approach of using VBScript to interact with HTTP response and request objects. In addition, HTML and JavaScript can be intermixed with the ASP code to create Web Forms. Although this offers a degree of flexibility, it often results in a babel of code and inconsistent coding techniques. Using ASP.NET to Implement a BMI CalculatorBefore building an ASP.NET solution for the calculator, let's first take a general look at the features of ASP.NET and how they affect Web Forms programming. One way to understand the Web Forms model is to look at the requirements faced by the ASP.NET designers梐nd how they met them.
ASP.NET offers three models for implementing a Web application:
None of the models offers a performance advantage over the others. This leaves the choice of model up to one's preference梠r need梖or code separation. Let's now examine the models by using each to implement the BMI application. Inline Code ModelThe code for the BMI Web Form application is shown in Listing 16-2. Although it resembles an HTML page, an .aspx page is actually an XML-formatted page. It is processed on the server and used to generate a mixture of HTML and JavaScript that is sent to the browser. Notice that this example contains actual C# code梑etween the <script> </script> tags梩hat calculates the BMI value. This method is executed on the server and is not visible as source code to the client. Listing 16-2. ASP.NET Inline Code Implementation of a BMI Calculator<%@ Page Language="C#" %> <HTML> <HEAD><TITLE>BMI Calculator</TITLE> <script runat="Server"> // Calculate BMI from values on form private void getBMI(object sender, System.EventArgs e) { try { decimal f = Convert.ToDecimal(htf.Value); decimal inch = Convert.ToDecimal(hti.Value); decimal w = Convert.ToDecimal(wt.Value); decimal totinches = f * 12 + inch; decimal h2 = totinches * totinches; decimal massIndex = (w * 703 * 10/ h2)/10; bmi.Value = massIndex.ToString("##.##"); }catch (Exception ex) { bmi.Value=" "; } } </script> </HEAD> <BODY bgcolor=#ffffff> <FORM NAME="bmi_input" runat=server> <table border=0 cellpadding=2 cellspacing=0 width= 180 bgcolor=#cccccc> <tr><td colspan=3 align=center><font size=2> <b>BMI Calculator</b> </td></tr> <tr><td><font size=2 ><b>BMI:</b></td> <td colspan=2 ><input type=text size=5 id=bmi runat=server></td></tr> <tr><td colspan=3><hr size=1></td> </tr> <tr><td><font size=2 >Height:</td> <td><input type=text size=3 id=htf maxlength=1 runat=server></td> <td><input type=text size=3 id=hti maxlength=2 runat=server></td> </tr> <tr><td> </td><td valign=top><font size=2>feet</td> <td valign=top><font size=2>inches</td> </tr> <tr><td><font size=2 >Weight:</td> <td colspan=2><input type=text size=3 id=wt maxlength=3 runat=server></td> </tr> <tr><td colspan=3 align=center> <INPUT TYPE="button" VALUE="Submit Form" OnServerClick="getBMI" id=bmiButton runat=server> </td> </tr> <tr><td colspan=3> </td> </tr> </table> </FORM> </body> </html> To understand the differences between standard HTML and ASP.NET code, let's compare how controls are specified in Listing 16-1 versus Listing 16-2.
ASP.NET also adds three hidden fields to the HTML page it returns to the browser: <input type="hidden" name="__EVENTTARGET" value="" /> <input type="hidden" name="__EVENTARGUMENT" value="" /> <input type="hidden" name="__VIEWSTATE" value="dDwxMzc5NjU4NTAwOzs+iIczTTLHA74jT/02tIwU9FRx5uc=" /> The first field, __EVENTTARGET, specifies the control that invoked the request (known as a postback) to the server; the second, __EVENTARGUMENT, contains any parameters required by the event. The __VIEWSTATE field is by far the most interesting. View StateView state is the feature in ASP.NET that automatically maintains the state of server-side controls (controls declared with runat=server) as a form makes the round trip between the client and the server. In other words, it allows a page to place data in a control such as a ListBox or GridView one time梪sually when the page is first loaded梐nd ensures the data is retained as subsequent postbacks occur. Here is how it works. When a page is posted back to the server, the data in the hidden __VIEWSTATE field is deserialized and used to set the state of controls and the overall Web page. Data received in the HTTP request as part of a POST operation is used to set the values of those related controls (note that for controls whose contents are posted?tt>TextBox, CheckBox, RadioButtons梩he posted data overwrites the view state data). The __VIEWSTATE field is then updated before it is passed back to the client. The returned view state value plays no role on the client other than to represent a snapshot of control values at the time the page is received by the browser. Because the view state string can be viewed in a source listing, questions about security become a legitimate issue. However, unlike the query string, the value is not represented as clear text. value="dDwxMzc5NjU4NTAwOzs+iIczTTLHA74jT/02tIwU9FRx5uc=" By default, a machine-specific authentication code is calculated on the data and appended to the view state string. The full string is then Base64 encoded. It is possible to decode the string, but the difficulty in doing so will thwart most casual efforts. Tampering with the string can also be detected by the server and results in a security exception being thrown. As always, use Secure Sockets Layer (SSL) to ensure absolute security for Internet communications. Core Note
Performance is another issue that must be considered when working with the view state value. By default, it maintains data for all server-side controls on the form. The control information is not limited to only the data value associated with the control. For example, when a DataGrid is used, the view state includes not only the data in each cell, but also column and row headers, and related style attributes. The view state data can easily add several thousand bytes to a Web page and slow performance. To improve performance, you may want to disable view state for the Web page and apply it only to selected controls. Set the EnableViewState attribute in the @Page directive to disable it at the page level: <%@ Page Language="C#" EnableViewState="False" %> Then, to enable view state for an individual control, apply the attribute as shown in the following code: <input type=text size=3 id=wt maxlength=3 EnableViewState=true runat=server > Of course, you can also take the opposite tact and leave view state on for the page and turn it off for selective controls. The decision to enable or disable view state is one of the key decisions in designing a Web page that displays large amounts of data in a server-side control. The easiest approach is to allow ViewState to take care of the details. However, this can result in a large HTML payload being transferred repeatedly between browser and server. An alternative is to design the code to reload the data into the controls on each postback. The data may be fetched from the original source梪sually a database梠r it may be stored on the server in session state or a cache. These last two options are described in Chapter 17, "The ASP.NET Application Environment." Core Note The @Page DirectiveThe last element to discuss in Listing 16-2 is the @Page directive. An .aspx file can contain only one @Page directive, and it is typically梐lthough not required梩he first statement in the file. The purpose of this directive is to assign attribute values that control the overall behavior of the Web page, as well as specify how the page is assembled and compiled on the server. Table 16-1 lists selected attributes for the @Page directive.
The Codebehind, Codefile, and Src attributes specify the assembly or source file containing the business logic code for the page. Instead of placing code between <script></script> tags as we did in Listing 16-2, the code is placed in a separate code-behind file that is referenced by these attributes. Before discussing code-behind, let's look at some additional directives that are frequently used in .aspx pages. Other Directives@Import DirectiveThis directive is used to import a namespace in an .aspx page. It serves the same purpose as the C# using statement. <%@ Import namespace="System.Net" %> Several namespaces are automatically imported in a page, making this directive unnecessary in most cases. These namespaces include
@Assembly DirectiveThis directive links an assembly to the current page while the page is being compiled. This provides the page with access to all types in the assembly. It takes two forms: <%@ Assembly Name="webfunctions" %> <%@ Assembly Src="webfunctions.cs" %> The first version references an assembly that may be private or deployed in the Global Assembly Cache; the second statement causes the source to be dynamically compiled into an assembly that is linked to the Web page. Note that assemblies in the application's \bin subdirectory are automatically linked to a page and do not need to be referenced. @Register DirectiveThis directive associates alias names with namespaces and classes. Its purpose is to provide a convenient syntax for adding custom controls to a Web page. The directive takes two forms: <%@ Register Tagprefix="tagprefix" Namespace="namespace" Assembly="assembly" %> <%@ Register Tagprefix="tagprefix" Tagname="tagname" Src="pathname" %> Attributes:
The first form of the directive is used to add an ASP.NET server control to a page; the second form is used with a custom control contained in a source file. In the latter case, the TagPrefix and TagName are always used together as a colon-separated pair. Here is a code segment that places a user control defined in the file hdr.ascx on a Web page. The @Register directive defines the alias pair that is used to declare the control on the Web page. <%@ Register TagPrefix="uc1" TagName="hdr" Src="hdr.ascx" %> <form method="post" runat="server"> <uc1:hdr runat="server"></uc1:hdr> </form> We'll make use of this directive in Section 16.4, which provides examples of how to create and use custom controls. Note that @Register directive information also can be stored in the Web.config file (see Chapter 17), eliminating the need to place it in a Web page. The Code-Behind ModelThe example in Listing 16-2 contains both C# to implement program logic and HTML to render the user interface. A Web page can also be configured as an .aspx file, containing only the interface code and a separate code-behind file that contains the program logic and serves as the base class for compiling the .aspx file (see Figure 16-4). This code-behind file takes the .cs extension. Figure 16-4. How ASP.NET responds to a Web page requestThe code-behind page is linked to the .aspx file as an assembly or source file using the Codebehind or Src attributes of the @Page directive. If the Codebehind attribute is used, the assembly must be stored in the \bin directory of the application. Let's now look at how the code in Listing 16-2 can be changed to use a code-behind file. We create a code-behind file named bmicb.cs (see Listing 16-3) to replace the code currently between the <script/> tags. The @Page directive links this file to the .aspx file: <%@ Page Language="C#" Src="bmicb.cs" Inherits="BMI" %> The code-behind page is always structured as a class whose name must be specified by an Inherits attribute. This class is shown in Listing 16-3. Let's take a close look at it, because knowledge of how the code-behind file and the .aspx file interact on the server is essential to understanding the ASP.NET Web page model. Listing 16-3. Code-Behind File for BMI Calculator?tt>bmicb.csusing System; using System.Web.UI.HtmlControls; public class BMI : System.Web.UI.Page { // <input type=text id=htf runat=server> protected HtmlInputText htf; // <input type=text id=hti runat=server> protected HtmlInputText hti; // <input type=text id=wt runat=server> protected HtmlInputText wt; // <input type=text id=bmi runat=server> protected HtmlInputText bmi; // <input type="button" VALUE="Submit Form" id=bmiButton // runat=server> protected HtmlInputButton bmiButton; override protected void OnInit(EventArgs e) { // Delegate to handle button click on client bmiButton.ServerClick += new EventHandler(getBMI); } protected void getBMI(object sender, System.EventArgs e) { decimal f = Convert.ToDecimal(htf.Value); decimal inch = Convert.ToDecimal(hti.Value); decimal w = Convert.ToDecimal(wt.Value); decimal totinches = f * 12 + inch; decimal h2 = totinches * totinches; decimal massIndex = (w * 703 * 10/ h2)/10; bmi.Value = massIndex.ToString("##.##"); } } The first thing to observe from this listing is that it consists of one class?tt>BMI梩hat derives from the System.Web.UI.Page class. The Page class is to Web Forms what the Form class is to Windows Forms. Like the Form, it has a sequence of events that are fired when it is initialized and loaded. It also has several properties that control its behavior梞any of which correspond to the @Page directive attributes already discussed. We'll look at the Page class later in this section. One of the trickiest aspects of learning ASP.NET is grasping how server-side controls work梥pecifically, how the content and action of controls displayed on a browser are managed on the server. Figure 16-5 illustrates the relationship. Each server control is declared as a field in the BMI class. When the values of the controls are posted to the server, they are assigned as field values. In this example, all of the controls are HTML controls梩hat is, standard HTML controls with the runat=server attribute. Figure 16-5. Binding between code-behind page and .aspx pageThe id value in the tag must match the field name identically. The field types are defined in the System.Web.UI.HtmlControls namespace. Each HTML control has a one-to-one mapping with an HTML tag, as shown in Table 16-2.
Handling Events on the ServerIn our example, clicking the Submit button sends a request to the server to calculate and return a BMI value based on the form's content. The .aspx code for the button looks like this:
<INPUT TYPE="button" VALUE="Submit Form"
id=bmiButton runat=server>
Compare this with the tag defining the button in Listing 16-2: <INPUT TYPE="button" VALUE="Submit Form" OnServerClick="getBMI" id=bmiButton runat=server> This earlier code defines a method (getBMI) to be called when the click event occurs. Because our current example has the method placed in a code-behind file, there is no reference to it in the .aspx file. Instead, the server-side code handles the event using a standard delegate-based event handling approach. An event handler method (getBMI) is defined that matches the signature of the EventHandler delegate. Then, using the button's id value, we create a delegate instance that registers the method for the ServerClick event of the bmiButton control:
bmiButton.ServerClick += new EventHandler(getBMI);
When the button is clicked on the browser, the contents of the form are posted to the server, which recognizes the button click event and calls the appropriate event handler. This raises one obvious question: Because a form can contain any number of buttons, how does the server determine the event that triggered the post-back? The answer is that the name of the control causing the event is passed to the server in the __EVENTTARGET hidden field that was discussed earlier. This is handled automatically by ASP.NET; the developer's responsibility is to create the delegate and server-side control event handler. Code-Behind with Partial ClassesThe problem with the preceding code-behind model is that each control in the markup page must be explicitly mapped to a protected member in the code page. Changes to the markup page require that the code page members be kept in sync. The use of a partial class in the code-behind page eliminates the need for the protected class member. The partial class is compiled with the markup page, which permits the markup and code sections to directly access each other's members. The effect is the same as using the inline model. To demonstrate this, extract the getBMI method from the inline code (refer to Listing 16-2) and place it in its own file inside a partial class. The result is a code-behind partial class as shown in Listing 16-4. Listing 16-4. Code-Behind Partial Class File for BMI Calculator
//file: bmi.aspx.cs
using System;
partial class BMICalc: System.Web.UI.Page{}
{
void getBMI (Object sender, EventArgs e)
{
try
{
decimal f = Convert.ToDecimal(htf.Value);
decimal inch = Convert.ToDecimal(hti.Value);
decimal w = Convert.ToDecimal(wt.Value);
decimal totinches = f * 12 + inch;
decimal h2 = totinches * totinches;
decimal massIndex = (w * 703 * 10/ h2)/10;
bmi.Value = massIndex.ToString("##.##");
} catch (Exception ex)
{ bmi.Value=" "; }
}
}
The client markup page links to this code by specifying the file name and the partial class name in its @Page declaration: <%@ Page codefile="bmi.aspx.cs" inherits="BMICalc" %> ASP.NET 2.0 continues to support the original code-behind model, but it should be used only for preexisting code. New development should employ the inline or partial class model. Page ClassThe first time an ASP.NET page is accessed, it is parsed and compiled into an assembly. This is a relatively slow process that results in the delay one notices the first time the .aspx page is called. Subsequent requests receive much faster responses because the assembly handles them. This assembly consists of a single class that contains all of the server-side code, as well as static HTML code. The compiled class derives either directly from the System.Web.UI.Page class or indirectly via an intermediate code-behind class. It is important to understand the members of the Page class. Its methods and properties define much of the functionality the .aspx code relies on for handling requests, and its events define junctures at which the code must perform initialization and housekeeping tasks. Table 16-3 summarizes some of the important properties of the Page class.
The Application and Session properties provide state information for a Web application and are discussed in the next chapter. HttpRequest and HttpResponse ObjectsThe Request and Response properties expose underlying objects (HttpRequest and HttpResponse) that are used to interact with the incoming HTTP request and the outgoing HTTP response. These classes include properties and methods to read cookies from the client's machine, receive uploaded files, identify the browser, get the IP address of the client, and insert custom content into the outgoing HTTP body. Chapter 17 discusses these in detail, but as an introduction, let's look a simple code example that illustrates the fundamentals of accessing these objects within an .aspx page. The next code segment uses the Response.Output.Write method to write information into the HTTP content returned to a browser. The information comes from Request.Browser properties that indicate the type of client. Note that by using <% %> tags in an .aspx file, we can intersperse these statements with the HTML code. Do this judiciously. An .aspx file is much easier to read when the C# code is segregated between <script> tags, as shown in Listing 16-2, or placed in a code-behind file.
<table border=0 cellpadding=0 cellspacing=0>
<%
Response.Output.Write(@"<tr><td>Browser Version: {0}
</td></tr>", Request.Browser.Type); // IE6
%>
</table>
Using IsPostBackThis useful property enables a Web application to distinguish between a postback and the first time a Web page is invoked. It lets the program know when to initialize values that only need to be set once. A typical example is a ListBox that contains unchanging values, such as all of the states in the United States. When assigned, these values are subsequently maintained in the __VIEWSTATE hidden field and do not need to be re-initialized. To demonstrate, let's extend our BMI inline code example to display the date and time when the user first requests the Web page. When displayed, this date and time remain unchanged no matter how many times the BMI calculation is subsequently requested. The date and time are displayed using a <span/> tag, which is added beneath the opening <FORM> tag (refer to Figure 16-2) in the bmi.aspx file. (This is equivalent to a Web control Label.)
<FORM NAME="bmi_input" runat=server>
<span id=sessionstart runat=server/><br>
In the code section, we must assign the date and time to the inner contents of the <span> tag the first time that the page is called. Here is the code to do this:
void Page_Load(object sender, EventArgs e)
{
if(!this.IsPostBack) sessionstart.InnerText =
DateTime.Now.ToString();
}
Recall that the code on the server is compiled into a class that inherits from the Page class. This class includes several events梔iscussed in the following section梩hat are triggered when a request is sent to the Web page. The most useful is the Page_Load event that is raised each time the page is loaded. Applications typically include an event hander for it that checks IsPostBack and performs initialization if the call is not a postback. In this example, the InnerText field of the <span> tags is set to the date and time the first time the page is loaded. Page EventsThe preceding example demonstrates how the Page_Load event handler provides a convenient place to initialize variables. The Load event is only one of four events defined by the System.Web.UI.Page class. The others are Init, PreRender, and UnLoad. These occur in a fixed sequence as shown in Figure 16-6. Figure 16-6. System.Web.UI.Page eventsTo best understand the role of each, let's look at what happens when a form is posted to a server:
Although Web Forms provide an event-based model that is similar to the Windows Forms model, the key difference is that the events do not actually fire until control returns to the server. There they must occur in the fixed order described in this section. Your code interacts with these events by overriding or replacing the event handlers for the events described in Figure 16-6. Cross-Page PostingA Web page in .NET 1.x could only post to itself. In 2.0, you can designate a target page, other than the current page, by setting the PostBackUrl property of a Button, ImageButton, or LinkButton to the address of the target page. Posting occurs when the button is clicked. To demonstrate, the button defined in this code posts the contents of the current form to nextstep.aspx when the button is clicked. <asp:button text="redirect" postbackurl="nextstep.aspx" runat="Server"> </asp:button> The page to which a form is posted can view the contents of the calling form using the PreviousPage property. In this example, nextstep.aspx uses PreviousPage to get the text value of the button that initiated the post. Of course, this technique would be used more often to gather data from text boxes on the posted form.
if(!this.IsPostBack)
{
// Sets text to the value of the Text property of the button
// from the calling form having the id postBtn: "redirect"
string text =
((Button)PreviousPage.FindControl("postBtn")).Text;
}
|
![]() |
< Day Day Up > |
![]() |