Rob Howard
When I was a kid, I spent a few weeks every year hanging out with my extended family. As a young American boy I was fascinated by Dutch electric trains, something I had never seen in my hometown of Dallas, Texas. My cousins treated me to a ride on their boat to watch a passing train. Sitting on the water close to the track, you can hear the approaching train, like a gentle whistle across the track, until it plays a slow climax when the train calls past. I couldn't help but be reminded of this when thinking about ASP.NET 2.0. ASP.NET 2.0 is very close and most of us are eagerly anticipating its release soon enough that we are even hearing the "woo" that the release continues to get louder and louder. Then the way we write software will change, once again.
Microsoft's ASP.NET 2.0 goal is to provide developers with 50% performance. However, the actual performance improvements appear to exceed expectations. New personalization, membership and role management features take the burden off developers, while other features, like data binding, are also simplified. For example, the familiar and still supported syntax:
<%# DataBinder.Eval (Container.DataItem, "FirstName") %>
In ASP.NET 2.0 it can be simplified to:
<%# Eval("FirstName") %>
Not only are there a ton of impressive new features, but there are also a ton of meaningful server controls. The ASP.NET programming model will become even more powerful in ASP.NET 2.0 due to the integration of membership with server controls like the <ASP:login> control and new data source and data control server controls.
The number of System.Web class libraries has almost doubled in ASP.NET 2.0 - so much coverage that it even requires a magazine column. To truly understand the extent of these changes, you'll need a new ASP.NET 2.0 book. I plan to write some columns here to highlight some of the more important new features of ASP.NET 2.0. This month I'm going to focus on navigation and page flow, starting with a much sought after feature - the ability to submit to other pages.
Cross-page delivery
The biggest complaint I hear from developers migrating to ASP.NET is the page postback model. ASP.NET pages can have a single <form> and can only HTTP post back to themselves, so all processing All logic will run on this page.
Many developers, especially those who are familiar with ASP and like to control the <form> element, will know that in ASP you can instruct the <form> where and how to submit its content data (HTTP Post or HTTP Get), and the same page The quantity of <form>. But compared with ASP, ASP.NET only allows a page to have only one <form runat=server>, and it can only be posted back to itself. This can be very frustrating. Here is an example of what is sent to other pages in ASP.NET 2.0:
<%@ Page MasterPageFile="~/Site.master" Language="C#"
CodeFile="Source.aspx.cs"
Inherits="Source" %>
<ASP:Content ID="MainContent"
ContentPlaceHolderID="Main" Runat="server">
Enter your name:
<ASP:TextBox ID="NameBox" Runat="server"></ASP:TextBox>
<ASP:Button ID="Button1" Runat="server" Text="Submit" />
</ASP:Content>
Master Pages are used to control page layout, with an <ASP:content> block and some server controls to accept user input.
If you plan to pass content to another page, you can use server code similar to the following:
Response.Redirect("Target.aspx?Name= " +
HttpUtility.UrlEncode(NameBox.Text));
The problem with this technology is that when the user clicks the button to submit, the server accepts the request and sends a response to redirect the browser to Target.aspx. Such a simple problem has done a lot of work!
Can the work be simplified? In ASP.NET 2.0 the answer is yes. Next, demonstrate the improved code:
<%@ Page MasterPageFile="~/Site.master" Language="C#"
CodeFile="Source.aspx.cs"
Inherits="Source" %>
<ASP:Content ID="MainContent"
ContentPlaceHolderID="Main" Runat="server">
Enter your name:
<ASP:TextBox ID="NameBox" Runat="server"></ASP:TextBox>
<ASP:Button ID="Button1" Runat="server" Text="Submit"
PostBackUrl="~/Target.aspx" />
</ASP:Content>
Note the PostBackUrl attribute in <ASP:Button>. This attribute tells the button not to perform the default postback but to submit data directly to Target.aspx.
You may be wondering how this works, especially if you are familiar with ASP.NET ViewState object. But that's beyond the scope of this article, when the cross-page delivery feature is used, a new hidden field will be added to the page:
<input type="hidden" name="__PREVIOUSPAGE" id="__PREVIOUSPAGE"
value="p1-dFHlCpgH2alr1vkr3G21UIR7jOuzn074led6lbGf1KQ47_F25GwG0" />
It's a bit like the view state generated by the control tree, but it is a fragment of the view state that validates the page for cross-page delivery. You know, when a page is cross-posted to another page, the receiving page needs to be able to access the instance of the posting page. In this case it means that Target.ASP can access the details of Source.aspx. In fact, a more efficient approach is to access the API from Source.aspx to Target.aspx through a strongly typed manager. In order to access the delivery page (previous page), ASP.NET2.0 provides a page attribute for cross-page delivery: PreviousPage.
PreviousPage returns the instance of the delivery page, and there is also a property used to check whether it is cross-page delivery: IsCrossPagePostBack. This property is similar to the existing IsPostBack but returns true only if a cross-page post occurs.
The PreviousPage property can behave differently. The default simply returns an instance of the previous page as a Page type. However, by using a new directive you can have the PreviousPage property return a strongly typed instance to access the public members of the page. For example, add the following code to Target.aspx:
<%@ PreviousPageType VirtualPath="~/Source.aspx" %>
You can now use the PreviousPage property on Target.aspx to access the data of Source.aspx. However, in order to access a server control, like the NameBox on Source.aspx, you also need to write the following code:
TextBox nameBox = PreviousPage.FindControl("NameBox") as TextBox;
In other words, you must use FindControl to access the control tree. Why? Server controls default to protected member variables. In order to have truly simple access to the elements of the previous page, you need to expose the property or method on Source.aspx as public, and then the following code will work: TextBox nameBox = PreviousPage. NameBox;
Cross-page delivery is a great feature of ASP.NET. There are some articles that discuss the technical details of cross-page delivery in depth. If you are interested in how cross-page delivery works, you can check out Dino Esposito's Cutting in the September issue of MSDN Magazine Edge column (please see my translation: ASP.NET Form (Translation)). You'll also likely find that if you're proficient in ASP.NET, you'll continue to use the standard page postback model most of the time. (Translator: The implication is that if you are an expert, you will disdain this feature)
The wizard control
can easily build a complex navigation function for the application through cross-page delivery. However, this feature does not make it easier to build wizard-style user interfaces. Wizard-style user interfaces, whether linear or non-linear, are often designed to accomplish tasks. It provides end-users with a user-friendly way to complete a complex series of steps, each of which is broken into chunks.
In ASP.NET 1.x, wizards were often implemented using a few tricks: placing multiple <ASP:panel> server controls on the same page and switching visibility based on the user's location. Writing a wizard in ASP.NET is not an easy task. Many designers abandon the wizard, and the management of the step process is also confusing.
The new cross-page delivery capabilities in ASP.NET can be used to solve the wizard problem, but it is also a challenge when non-linear navigation is required. For example, step 1, step 2, skip steps 3-5, step 6, step 3, step 2, step 6, the ASP.NET 2.0 wizard control solves most of these problems. Also, all input elements of the cross-page delivery wizard are continuously accessible through the page postback model.
The functionality of the wizard control is very close to the way of hiding panels in ASP.NET 1.1. However, the wizard control exposes a series of <ASP:WizardStep>, which can contain any number of child controls. However, each <ASP:WizardStep> needs to have its own unique ID, see Figure 1. The wizard control page manages all navigation, supports linear and non-linear navigation, and has full design-time support. Figure 2 demonstrates the wizard control. The left side is link-based non-linear navigation, and the lower right side is linear button navigation. From the task menu that opens, you can see not just a common task but a list of steps allowing switching between steps at design time.
Figure 2 Wizard in Visual Studio
All visible elements of the wizard control are configurable. Non-linear links can be replaced by buttons or delete entries, and previous, next, and completed linear navigation elements can also be changed into picture buttons or links. In fact, all aspects of the control can be configured through templates.
One of the difficulties in writing wizard controls in ASP.NET 1.1 was managing where the user should be. The wizard control simplifies this task by exposing the ActiveStep property. The ActiveStep property can query and determine which step is currently active. The natural flow of the wizard will proceed as declared by the implementation, and the flow can be changed at any time through the MoveTo method. Through MoveTo, any step can be set as ActiveStep. In order to assist navigation and process, several events are also provided, see Figure 3.
The new wizard control is very useful when collecting user information. You don't want to write all the basic structures in ASP.NET 1.1. ASP.NET has done all the work for you. The wizard control is so useful that the ast.net team uses it as the base class for the CreateUserWizard control, which is used to create users as part of the Membership function.
The sections
Cross-page posting and the <ASP:Wizard> control give ASP.NET developers several new options for controlling the navigation flow in their applications. Cross-page delivery is useful in situations where you currently need to use Response.Redirect or Server.Transfer. Wizard controls are great for building complex data collections that require both linear and non-linear data collection.
--------------------------------------------------------
Figure 1 Wizard steps
<ASP:Wizard runat="server" >
<WizardSteps>
<ASP:WizardStep ID="Step1">
Welcome!
</ASP:WizardStep>
<ASP:WizardStep ID="Step2">
What is your name: [TextBox1]
[Button1]
</ASP:WizardStep>
<ASP:WizardStep ID="Step3">
Thank you, [TextBox1.Text]!
</ASP:WizardStep>
</WizardSteps>
</ASP:Wizard>
----------------------------------------------- ----------
Figure 3 Navigation Events
Event | Description |
---|---|
ActiveStepChanged | Raised when the ActiveStep is set to a new WizardStep |
CancelButtonClick | Raised when the button identified as the Cancel button is clicked |
FinishButtonClick | Raised when the button identified as the Finish button is clicked |
NextButtonClick | Raised when the button identified as the Next button is clicked |
PreviousButtonClick | Raised when the button identified as Previous button is clicked |
SideBarButtonClick | Raised when one of the SideBar links or buttons is clicked |