ASP.NET 1.1 Insider Solutions- P2

Chia sẻ: Thanh Cong | Ngày: | Loại File: PDF | Số trang:50

lượt xem

ASP.NET 1.1 Insider Solutions- P2

Mô tả tài liệu
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Tham khảo tài liệu ' 1.1 insider solutions- p2', công nghệ thông tin, kỹ thuật lập trình phục vụ nhu cầu học tập, nghiên cứu và làm việc hiệu quả

Chủ đề:

Nội dung Text: ASP.NET 1.1 Insider Solutions- P2

  1. 38 1 Web Forms Tips and Tricks LISTING 1.14 Continued You might like to experiment with the CellPadding and CellSpacing properties of the DataGrid control, as well as with different values of the border style selector, to get a different appearance for the scrollable regions. For example, “style=border:3 inset” when CellPadding and CellSpacing are both zero gives a very compact grid-like effect. Loading Controls Dynamically at Runtime When the ASP team at Microsoft was designing ASP.NET, it probably seemed obvious that the way forward was to compile the pages into some kind of executable code. This approach means that there is a distinct separation between the tasks (and the amount of processing work ASP.NET has to do) of generating a page the first time it is executed—when it has to be compiled and the resulting code written to disk—and subsequent executions of the compiled code. As a result, the way that the structure and content of a page are discovered and created from a file containing declarative definitions and code in sections only affects the “initial hit” performance and not the performance on subsequent requests. Consequently, this has provided a development environment that supports quite complex page creation tech- niques, such as the use of server controls and user controls, page and control state maintenance, and dynamic creation of a control tree for the page. In particular, the use of a developer-accessible control tree has made it really easy to use ASP.NET to build pages that, in ASP 3.0 and many other Web development environments, would required complicated Response.Write statements, #include directives, and other tricks. Being able to create controls dynamically at runtime, meanwhile, is extremely useful if you don’t know beforehand how many instances of a particular control you need on the page. For example, you might need to create a number of text boxes or buttons, depending on the value entered by the user, which could therefore be different each time the page is executed. The ASP.NET Control Tree As ASP.NET processes a page, it generates a control tree that contains references to all the server controls on the page. Note that this only includes server controls—basically declarative elements that contain the runat=”server” attribute. Figure 1.10 shows a conceptual view of a page that
  2. Loading Controls Dynamically at Runtime 39 contains several server controls, including a server-side element that contains many of the controls on the page. Notice also that the Hyperlink and HtmlAnchor ( element) controls in this example have child Image and HtmlImage controls. These represent the typical output that provides clickable images: FIGURE 1.10 A conceptual view of an Page ASP.NET page that contains nested controls. HtmlGenericControl Label HtmlForm Label TextBox Image HtmlInputFile CheckBox Button Hyperlink Image HtmlAnchor HtmlImage In more technical terms, the page consists of a hierarchy of control instances. Figure 1.11 shows this in tree form. Each object in the tree is a server control that is descended directly or indi- rectly from System.Web.UI.Control and thus exposes a Controls property that references a ControlCollection instance. Each ControlCollection instance is, as you might guess, a collection of references to all the child controls for that control. You can manipulate the control tree by adding controls to and removing them from these ControlCollection instances. When the page is rendered, the control tree is used to build the HTML (or other output) that is sent to the client. Table 1.1 shows the properties and methods of the ControlCollection object that are useful when manipulating the control tree.
  3. 40 1 Web Forms Tips and Tricks FIGURE 1.11 Page The ASP .NET control tree for the page shown in Figure 1.10. HtmlGeneric Label HtmlForm HtmlAnchor Control HtmlImage Label Image CheckBox Hyperlink TextBox HtmlInputFile Button Image TA B L E 1 . 1 The Members of the ControlCollection Object for Working with, Adding, and Removing Controls Property or Method Description Count Returns the number of controls in the ControlCollection instance. Item Acts as the indexer for the zero-based ControlCollection instance, returning a reference to a control within the collection. Add(control) Adds the Control instance referenced by the control parameter to the end of the ControlCollection instance of this control. AddAt(index, control) Inserts the Control instance referenced by the control parameter into the ControlCollection instance of this control at the specified Integer index. Clear() Removes all the controls from the ControlCollection instance of this control. Contains(control) Returns a Boolean value indicating whether the Control instance referenced in the control parameter is a member of this control’s ControlCollection instance. IndexOf(control) Returns the Integer index of the Control instance referenced in the control parameter within this control’s ControlCollection instance. Remove(control) Removes the Control instance referenced in the control parameter from this control’s ControlCollection instance. RemoveAt(index) Removes the Control instance at the specified Integer index from this control’s ControlCollection instance. Adding Controls to the Control Tree In most cases, you can just use the Add method to add controls to the control tree in the correct order to produce the output you want. This is generally easier than trying to figure out where to insert a control within a collection, although the other methods are useful if you need to do any complex management of the child controls for a particular control. Probably the easiest way to insert a control into a page at a specific point is to use an ASP.NET PlaceHolder control. This generates no output in the page, but it does expose a ControlCollection instance to which you can add other controls. When you use this approach, the newly added
  4. Loading Controls Dynamically at Runtime 41 controls will always appear in the same position in the page, even if you later add or remove controls from elsewhere in the control tree or the parent control’s ControlCollection instance. The following code demonstrates the use of the PlaceHolder control. In the Page_Load event, you just create a new Hyperlink control and set the NavigateUrl property. Then you create a new Image control and specify its ImageUrl property. Next, you add the Image control to the ControlCollection instance of the Hyperlink control and add the Hyperlink control to the ControlCollection instance of the PlaceHolder control: ... Sub Page_Load() Dim oLink As New Hyperlink() oLink.NavigateUrl = “” Dim oImage As New Image() oImage.ImageUrl = “~/images/True.gif” oLink.Controls.Add(oImage) ph1.Controls.Add(oLink) End Sub When the page is rendered, the following The Actual Output Format output is generated (ASP.NET automatically The output is not actually indented as shown adds the border=”0” attribute): here, but instead is generated as a single line with no spaces or carriage returns. In this example it is formatted with carriage returns and indented so that you can see the result more clearly. Creating a DataGrid Control Dynamically at Runtime Compared to the previous, somewhat trivial example, the following example generates a more complex page which contains a DataGrid control that supports inline editing. The result is shown in Figure 1.12. FIGURE 1.12 A dynamically generated DataGrid control.
  5. 42 1 Web Forms Tips and Tricks The page contains all the server-side code to handle the events in the DataGrid control, using the same techniques in the first example in this chapter. (We won’t be looking at that code here.) With this example, we are interested in the way that the DataGrid control itself is generated. The HTML section of the sample page contains a server-side element, but no other content: Instead, the DataGrid control and the Label Choosing the Event when Adding Controls control used to display any data access errors Instead of generating the controls during are added to the page dynamically during the other ASP.NET page events, such as Init or Page_Load event. Also, the various events in Render, we had most success getting the the DataGrid control are wired to the appropri- process to work reliably, especially when ate event handlers already located in the wiring up event handlers, by using the Page_Load event. The controls must be section of the page. generated on every postback (not just when The previous example uses a PlaceHolder the page is first loaded) and in exactly the control as the container to which the new same order and with the same ID values. controls are added. However, a server-side Unlike control values, dynamically generated element works just as well, and in this controls are not maintained in the viewstate of the page. However, values are maintained example you can add the controls directly to and will be reloaded after the controls have the ControlCollection instance of the HtmlForm been created and added to the control tree. control that implements the server-side control. Setting Size and Color Properties Dynamically You can generate values for some of the properties of Web Forms server controls. Properties that set the color of parts of the output, such as ForeColor and BackColor, accept references to a Color structure. Properties that accept sizes, such as Width and BorderWidth, accept references to a Unit structure. When declaring a server control in the HTML section of the page, you can use the color names or size values directly, as in this example: However, to set these properties dynamically, you have to provide an instance of the correct structure classes. Here’s an example: oGrid.HeaderStyle.ForeColor = Color.FromName(“#ffffff”) oGrid.HeaderStyle.BackColor = Color.FromName(“#b50055”) oGrid.ItemStyle.BorderWidth = Unit.Pixel(1) The Unit structure is part of the System.Web.UI.WebControls namespace, so it is available by default in all ASP.NET Web pages. However, the Color structure is defined in the System.Drawing
  6. Loading Controls Dynamically at Runtime 43 namespace, which is not imported into ASP.NET pages by default. Therefore, you have to include the appropriate Import directive in any pages that reference a Color structure: Creating the DataGrid Control Creating the DataGrid control itself is not difficult; it just requires quite a lot of repetitive code. You create an instance of a DataGrid control, set all the properties, and then you add it to the Controls collection of the element in the page. You do the same with the Label control that will display any data access errors. Listing 1.15 shows the declaration of two page-level variables that are used to hold references to the new controls (so that they can be accessed in routines other than the Page_Load event handler), followed by the start of the Page_Load event handler. Here, you create the DataGrid control and add all the properties that set the appearance and behavior of the control. You can reduce the amount of code required by taking advantage of the Visual Basic .NET With construct. Notice how you set the properties of objects that are actually children of the DataGrid control, such as the HeaderStyle, ItemStyle, and AlternatingItemStyle objects. You can use a nested With construct or just reference them by using a period to access the child objects. LISTING 1.15 Dynamically Generating a DataGrid Control Dim oGrid As DataGrid Dim oLabel As Label Sub Page_Load() ‘ create a DataGrid control oGrid = New DataGrid() ‘ set control properties With oGrid .id = “dgr1” .BorderStyle = BorderStyle.None .BorderWidth = Unit.Pixel(0) .BackColor = Color.FromName(“#deba84”) .CellPadding = 3 .CellSpacing = 0 .DataKeyField = “CustomerID” .Width = Unit.Percentage(100) .AutoGenerateColumns = False With .HeaderStyle .Font.Bold = True .ForeColor = Color.FromName(“#ffffff”) .BackColor = Color.FromName(“#b50055”) End With
  7. 44 1 Web Forms Tips and Tricks LISTING 1.15 Continued .ItemStyle.BackColor = Color.FromName(“#fff7e7”) .AlternatingItemStyle.BackColor = Color.FromName(“#ffffc0”) End With ‘ create a column for the DataGrid control ‘ and set properties Dim oCol1 As New EditCommandColumn() With oCol1 .EditText = “Edit” .CancelText = “Cancel” .UpdateText = “Update” End With ‘ add column to DataGrid oGrid.Columns.Add(oCol1) ‘ repeat for remaining columns Dim oCol2 = New BoundColumn() With oCol2 .DataField = “CustomerID” .HeaderText = “ID” .ReadOnly = True End With oGrid.Columns.Add(oCol2) ... ‘ same for CompanyName, City, Country and Phone columns ... Toward the end of Listing 1.15, you can see the columns being added. You create an instance of the appropriate type of column, set the properties, and then add the column to the Columns collection. Like the Controls property, the Columns property of a DataGrid control is a collection of references to the columns that make up the DataGrid control. Listing 1.15 does not contain the declarations of the Company Name, City, Country, and Phone columns because they are identical to the Customer ID column (except, of course, that they refer to different columns in the source data). Wiring Up the DataGrid Control Events With the DataGrid control complete, you can attach its events to the appropriate event handler routines already present in the page, as shown in Listing 1.16. In Visual Basic .NET you use the AddHandler statement, and in C# you just append the event delegates by using the += operator. You can wire up the EditCommand, UpdateCommand, and CancelCommand events, targeting them at the
  8. Loading Controls Dynamically at Runtime 45 event handlers named DoItemEdit, DoItemUpdate, and DoItemCancel. This achieves the same result as declaring them directly in the page, as in the DataGrid control example earlier in this chapter: OnEditCommand=”DoItemEdit” OnUpdateCommand=”DoItemUpdate” OnCancelCommand=”DoItemCancel” LISTING 1.16 Wiring Up the Event Handlers, Creating the Label Control, and Populating the DataGrid Control ... ‘ add event handlers to the grid AddHandler oGrid.EditCommand, _ New DataGridCommandEventHandler(AddressOf DoItemEdit) AddHandler oGrid.UpdateCommand, _ New DataGridCommandEventHandler(AddressOf DoItemUpdate) AddHandler oGrid.CancelCommand, _ New DataGridCommandEventHandler(AddressOf DoItemCancel) ‘ create new Label control and set properties oLabel = New Label() With oLabel .id = “lblErr” .EnableViewState = False End With ‘ add new controls to page as children of frmMain.Controls.Add(oGrid) frmMain.Controls.Add(oLabel) ‘ only need to databind if it is not a postback ‘ viewstate used to populate dynamically added controls If Not Page.IsPostback Then oGrid.DataSource = GetCustomers() oGrid.DataBind() End If End Sub After attaching the event handlers, you generate a new Label control and set its properties. Then you add the DataGrid and the Label controls to the ControlCollection instance of the server-side control declared in the page (as shown in Listing 1.16). Populating the DataGrid Control The final task in this example, shown at the end of Listing 1.16, is to populate the DataGrid control. As long as the control tree you generate is the same every time the page is loaded, the
  9. 46 1 Web Forms Tips and Tricks values of all the controls will be maintained through the viewstate of the page—even for dynamically added controls. So you only have to perform the data binding to the data source if this is not a postback, just as you would if you had declared the DataGrid control directly within the HTML section of the page. The viewstate of the page also stores the values of many of the other properties of the controls on the page. So if you allow users to modify properties, such as whether specific columns are visible or the color of the text, you’ll want these values to be preserved across page loads and not be reset every time you regenerate the control. In this case, you can set the values only the first time the page loads, at the same time as populating the DataGrid control. For example, this code sets the style of the header row only when the page first loads, but it is maintained across postbacks within the viewstate of the page: If Not Page.IsPostback Then oGrid.DataSource = GetCustomers() oGrid.DataBind() oGrid.HeaderStyle.Font.Bold = True oGrid.HeaderStyle.ForeColor = Color.FromName(“#ffffff”) oGrid.HeaderStyle.BackColor = Color.FromName(“#b50055”) End If Loading User Controls Dynamically at Runtime The final topic we’ll briefly look at to finish this chapter is dynamically loading user controls at runtime. In theory, the principles are the same as for the DataGrid control; however, there are a couple things to be aware of with user controls. A user control is not strongly typed—in other words, it is usually generated as an instance of the generic UserControl class, whereas other server controls are specific classes from the .NET Framework class library. You can use the LoadControl method of the Page object to load a user control. The following code takes the path and name of the .ascx disk file and returns a reference to the control as a UserControl instance that you can add to the ControlCollection instance of any other control: Dim oNewCtrl As UserControl = LoadControl(“path-to-ascx-file”) oExistingControl.Controls.Add(oNewCtrl) This is fine if the user control is simply some static user interface content. However, if you want to access properties or other members of the user control, you have a problem because the UserControl class that represents the user control doesn’t expose them. In that case, you have to add to the page a reference to the user control, and you have to specify the classname of the user control in the .ascx file. When you insert a user control in the page declaratively, you use a Register directive to specify the tag prefix and tag name you’ll be using, and you use the path and name of the .ascx file that implements the user control. Here’s an example:
  10. Loading Controls Dynamically at Runtime 47 When you want to insert a user control dynamically and be able to access it as a strongly typed object, you use the Reference directive instead. The following example just takes the path and name of the user control: However, this assumes that the user control itself declares a classname. In the user control, you have to add the ClassName attribute to the Control directive, as in this example: Now you can use the CType statement in Visual Basic (or a direct cast in C#) to convert the UserControl reference into a reference to the specific class. For example, you can load an instance of the SpinBox user control you’ll be meeting later in this book and expose it as a UserSpinBox instance with the following code: Dim oCtrl As UserControl = LoadControl(“..\ascx\user-spinbox.ascx”) Dim oSpinBox As UserSpinBox = CType(oCtrl, UserSpinBox) Alternatively, if you just want to set a property (such as the Increment property), you can use something like this: Dim oCtrl As UserControl = LoadControl(“..\ascx\user-spinbox.ascx”) CType(oCtrl, UserSpinBox).Increment = 3 oPlaceHolder.Controls.Add(oCtrl) An Example of Loading a User Control To briefly demonstrate the dynamic loading of a user control, the final example in this chapter loads instances of the custom SpinBox user control, as shown in Figure 1.13. The page contains both a Register and a Reference directive for the SpinBox user control: The first SpinBox instance you see in the page is inserted declaratively, which is possible Running the SpinBox Example because of the presence of the Register direc- As you’ll see in Chapter 8, “Building Adaptive tive. However, as you can see from Listing Controls,” which discusses the SpinBox control, you have to copy a file that we 1.17, the remainder of the page is made up provide with the samples into the basically of three PlaceHolder controls where aspnet_client folder of your Web site for you can dynamically add the other instances this example to work. You should copy the of the SpinBox control. file spinbox.js from the samples into a new subfolder named custom within the aspnet_client folder of your Web site.
  11. 48 1 Web Forms Tips and Tricks FIGURE 1.13 A sample page that demon- strates loading user controls dynamically. LISTING 1.17 The Section of the Page and Declaration of One SpinBox Control Declared in HTML section of page: Created dynamically: Inserting three new control instances: Inserting three instances of the same control reference: Listing 1.18 shows the Page_Load event handler. You generate a SpinBox control as a UserControl instance, and then you set the Increment property by converting the reference into a UserSpinBox instance, before adding it to the ControlCollection instance of the first PlaceHolder control. Next, you add three separate new instances of the SpinBox control to the ControlCollection instance of the second PlaceHolder control. (You may have wondered if it is possible to use multiple instances of the same control.) You place each one on a new line by separating them with a element. Notice how you generate this by using an HtmlGenericControl instance, as mentioned earlier in this chapter. LISTING 1.18 The Page_Load Event Handler That Loads the SpinBox Control Instances Sub Page_Load() Dim oCtrl1 As UserControl = LoadControl(“..\spinbox\ascx\user-spinbox.ascx”)
  12. Summary 49 LISTING 1.18 Continued CType(oCtrl1, UserSpinBox).Increment = 3 ph1.Controls.Add(oCtrl1) Dim oCtrl2 As UserControl For iCount As Integer = 1 To 3 oCtrl2 = LoadControl(“..\spinbox\ascx\user-spinbox.ascx”) ph2.Controls.Add(oCtrl2) ph2.Controls.Add(New HtmlGenericControl(“br”)) Next Dim oCtrl3 As UserControl = LoadControl(“..\spinbox\ascx\user-spinbox.ascx”) For iCount As Integer = 1 To 3 ph3.Controls.Add(oCtrl3) ph3.Controls.Add(New HtmlGenericControl(“br”)) Next End Sub Finally, the code demonstrates a common mistake that some people make when inserting controls into a page dynamically. Instead of creating a new instance of the control each time (as in the previous For...Next loop with the LoadControl method), it simply loads the user control and then inserts it into the PlaceHolder control’s ControlCollection instance three times. If you look back at Figure 1.13, you’ll see that even though the control gets added three times, the sequence of actions that render the page remove all but the last instance. This is because the three references in the ControlCollection collection are all to the same instance of the user control. So remember to create new instances of your user controls if you want to insert multi- ple instances into the page. Summary This chapter covers quite a few different but interlinked topics. It starts with a look at how you can get more from the very clever ASP.NET validation controls. In particular, it looks at how you can use them with non-text controls and how you can validate other types of controls that do not directly support validation. This section of the chapter concludes with an example that uses the validation controls within a DataGrid control. Along the way, we looked at using images in a DataGrid control column to indicate Boolean values, populating and selecting values in simple nested list controls, and storing the source DataSet instance in the user’s ASP.NET session to improve performance and efficiency. Next, this chapter looks at some different issues with the DataGrid control, specifically aimed at exerting more control over presentation of the contents. It talks about how you can control the width of columns, edit more than one value in a cell, and provide scrolling in a cell to avoid having the DataGrid control expand vertically when long text strings are displayed.
  13. 50 1 Web Forms Tips and Tricks This chapter also looks at the techniques for inserting controls into a page dynamically. As well as covering some of the basic theory of the ASP.NET control tree, this chapter provides an example that dynamically creates a DataGrid control, complete with inline editing. This involves considering when to populate the grid, as well as wiring up the events in the DataGrid control to the appropriate event handlers. Finally, this chapter finishes with a look at the issues involved in loading user controls dynami- cally and being able to access their properties and methods as strongly typed objects.
  14. 2 IN THIS CHAPTER Techniques for Passing Values Between Pages 52 Cross-Page Client-Side Versus Server-Side Redirection 60 Posting Exposing Values to Another Page via References 62 Best Practice: Exposing Control Values or Control References As Properties 65 Isn’t it amazing how some people are never satisfied? In ASP 3.0, it was becoming the de Best Practice: Reducing Data rigueur approach to build pages that post Transfer Volumes by Using the back to themselves and include code that Server.Transfer Method 68 detects which button was clicked, extract The Server.Execute Method 68 the values of the HTML controls on the page, and then repopulate them. This Summary 72 required loads of fiddly work, inserting value and selected attributes into each control and building the decision constructs that decide which code to execute in response to the user’s action. Then along came ASP.NET, with its fiendishly clever postback architecture that does all the difficult stuff automatically. Hardly any code is required, there’s no need to poke around in the Request.Form and Request.QueryString collections, and even proper event handling is provided. So what do people keep asking how to do now? They want to post values back to a different page! A lot of programmers at Microsoft would be turning in their graves if they weren’t still alive to see it. However, because there actually are some legitimate situations in which this is useful, this chapter looks at the possibilities and tech- niques for implementing ASP.NET server- side forms that post back to different pages. You might want to do this if you need to
  15. 52 2 Cross-Page Posting take advantage of pages in another application or site but still want to use server controls in your page. Or you might want to reuse pages so that each one can receive values from several sources. Whatever the reason, this chapter demonstrates how you can achieve it. Techniques for Passing Values Between Pages ASP.NET engenders a postback architecture, where pages containing a server-side form (a element that contains the runat=”server” attribute) are always posted back to themselves. In fact, this is effectively enforced by ASP.NET, which doesn’t allow server-side code to set the action attribute of a server-side form (in other words, the Action property of the HtmlForm control instance that implements a server-side form) to any value other than the current URL. However, there are basically four ways that you can force a element to pass values to a different page: n Use a non-server control for the element—in other words, omit the runat=”server” attribute—This means that the page will behave just as in ASP 3.0, and you can collect the values in the controls on the form from the Request collections in the traditional way. This also allows you to have multiple forms on the page, but it prevents you from using many of the ASP.NET server controls on the form. It also prevents the ASP.NET postback architecture from working, so you cannot access the controls on the original page—you can access only their posted values. n Use client-side script to change the action attribute of the element after the page has loaded into the browser—However, this method requires the target page to have the MAC encoding check on the viewstate disabled to prevent an error. n Use the Response.Redirect method to load the target page after the values have been posted back to the original page—The submitted values must then be extracted from the Request collections, and you also have to use an intermediate page to handle the case where the method of the form is set to POST (the default for a server-side form) rather than GET. n Use the Server.Transfer or Server.Execute method to cause the second page to run within the context of the original page—In this case, you can expose values and controls as properties of the original page and access them in the target page. The user does not see the URL of the target page in his or her browser. This chapter does not look at the first of these techniques because it does not differ from tradi- tional pre-ASP.NET methods. However, it does look at two sample pages that explore the concepts of the other three techniques. Accessing Request Values in Another Page The sample page redirectpage.aspx, shown in Figure 2.1, allows you to experiment with the second and third of the techniques listed in the preceding section. The page contains several server-side controls, hosted within a server-side element. The first three (the text box, list,
  16. Techniques for Passing Values Between Pages 53 and drop-down list) are only there to provide values that will be passed to the target page. The option buttons allow you to select which method will be used: POST or GET. FIGURE 2.1 A sample page that demon- strates changing the action attribute and redirection. Below these controls are four buttons that submit the form to the server. The first two use client-side code to change the action attribute of the element before the page is submit- ted so that it is actually submitted to a different target page. The second two buttons are wired up to server-side event handlers that call the Response.Redirect method to load the target page. Changing the action Attribute of a Form The first two buttons in the sample page shown in Figure 2.1 are ordinary HTML elements that call a client-side script function named changeAction and pass to it the name of the target page that will be loaded:   The changeAction function simply changes the action attribute of the server-side element that contains all the controls on the page to the specified URL: function changeAction(sURL) { var theForm = document.getElementById(‘frmMain’); theForm.action = sURL; } In the case of the first button, the target page is catchrequest.aspx. This page contains an ASP.NET Label control and a server-side element with an ASP.NET Button control:
  17. 54 2 Cross-Page Posting Values in the Request collections: The server-side code in this page, shown in Listing 2.1, implements a Page_Load event handler that simply iterates through the Request.QueryString and Request.Form collections, collecting any values stored there and displaying them in the Label control. The GoBack event handler, which executes when the button on the page captioned Back is clicked, redirects the browser back to the original page. LISTING 2.1 The Page_Load and GoBack Event Handler Routines Sub Page_Load() If Not Page.IsPostback Then ‘ display the values in the Request collections lblRequest.Text &= “* QueryString collection:” For Each oValue As String In Request.QueryString lblRequest.Text &= “  “ & oValue & “ = “ _ & Request.QueryString(oValue) & “” Next lblRequest.Text &= “* Form collection:” For Each oValue As String In Request.Form lblRequest.Text &= “  “ & oValue & “ = “ _ & Request.Form(oValue) & “” Next End If End Sub ‘ return to previous page and end current response Sub GoBack(sender As Object, args As EventArgs) Response.Redirect(“redirectpage.aspx”, True) End Sub When you try this example by clicking the Submit (Normal) button in the original page, you see an ASP.NET error page, indicating that the viewstate for the page is corrupted (see Figure 2.2). This is because ASP.NET encodes the viewstate it stores in the page along with the control tree and other details of the original page. When a postback occurs, ASP.NET validates this encoded data against the current page to act as a guard against malicious spoofing or other attacks. Because the page that is now executing is different from the original page, the validation check fails.
  18. Techniques for Passing Values Between Pages 55 FIGURE 2.2 The error message displayed when the view- state validation check fails. Turning Off Viewstate Validation You can get around the failed validation check problem by turning off viewstate validation in the target page. This means, of course, that the target page is no longer protected against spoof- ing, so if you use this technique, you must be sure to fully validate any submitted values to prevent malicious activity. To turn off viewstate validation, you simply add the attribute EnableViewStateMac=”False” to the Page directive. In this example, clicking the Submit (No MAC Check) button on the original page changes the action attribute of the form to point to the page catchnomac.aspx. This page is identi- cal to the catchrequest.aspx page, except that it also contains the EnableViewStateMac=”False” attribute. The result of clicking this button is shown in Figure 2.3, where you can see that now the values in the Request.Form collection are available and displayed. Changing the Method Property of a Server-Side Form Control In the example described in the preceding section, the values in the element are posted to the server because the default for the method attribute of a server-side form is POST. However, you can change it to GET by adding the method=”get” attribute to the declaration of the control: You can also change the Method property by using server-side code in your ASP.NET page or with client-side script code. The sample page allows you to change the method attribute of the form by using client-side script, which means that you can choose the method you want to use before submitting the form. Figure 2.4 shows the two option buttons for this, which are located on the page above the four submit buttons.
  19. 56 2 Cross-Page Posting FIGURE 2.3 Turning off viewstate validation to allow the target page to execute. FIGURE 2.4 Changing the Method property of a server-side form. Listing 2.2 shows the declaration of the RadioButtonList control that creates these option buttons. It has AutoPostback set to True, and any change to the selected index executes the server-side event handler named ChangeMethod (also shown in Listing 2.2). This just sets the Method attribute to the selected value. LISTING 2.2 A RadioButtonList Control and an Event Handler to Change the Method of a Form ... Sub ChangeMethod(sender As Object, args As EventArgs) frmMain.Method = optMethod.SelectedValue End Sub If you select the GET option button and then click the Submit (No MAC Check) button again, the values then appear in the Request.QueryString collection instead of in the Request.Form collection. They are also visible in the browser’s address bar, appended to the URL as the query string.
  20. Techniques for Passing Values Between Pages 57 Redirecting Postbacks to the Target Page The two submit actions described in the preceding section work by fooling the browser and ASP.NET into working just like they do in ASP 3.0 and earlier. The browser automatically posts the values of the elements on the form or sends them as a query string, depending on the value of the method attribute of the element. The technique that this section examines uses a different approach. You allow ASP.NET to Halting Execution by Using the perform a postback in the usual way, but then Response.Redirect Method you perform redirection to the target page by The Redirect method has two overloads. using the Response.Redirect method in the The first takes a single parameter—the URL of the page to redirect to. The second over- server-side code. load accepts an additional Boolean parame- The server-side event handler named ter, which indicates whether processing of the DoRedirect, which you attach to the Redirect current page should be halted. Usually, when button on the original page, looks like this: you perform a redirection, you set this second parameter to True. However, in some cases Sub DoRedirect(sender As Object, _ you might like to continue executing the origi- args As EventArgs) nal page code—even though the output from Response.Redirect(“catchrequest.aspx”, _ the page will not be sent to the client. For True) example, you might want to redirect the user End Sub to a different page when an error occurs but allow the original page code to clean up any resources it’s using, such as closing database It simply redirects the browser to the same connections. You can always halt execution catchrequest.aspx page (described in Listing later by calling the Response.End method. 2.1) that displays the values in the Request.QueryString and Request.Form collec- tions. However, if you click the Redirect button, you’ll see that there are no values sent from the page following a call to the Response.Redirect method (see Figure 2.5). FIGURE 2.5 The Response.Redirect method does not pass values to the target page. Passing Form Values to a Target Page by Using Response.Redirect Listing 2.3 shows the server-side event handler that is attached to the Redirect with Values button, the last of the four buttons on the original sample page. Similar to the Redirect button, it performs a redirection to the catchrequest.aspx page, which displays the values in the Request.QueryString and Request.Form collections. However, before it does this, it creates a query string containing the values of the text box, list, drop-down list, and option buttons on the page (you don’t pass the values of the four buttons).
Đồng bộ tài khoản