Traditionally, in ASP.NET 1.0/1.1, a page would post to itself and have access to the controls. There was no easy way to post to some other page and retain access to the pages form and controls. Cross-page posting was introduced in ASP.NET 2.0 and allows a form to be submitted to another page. The page has access to the forms controls.
Implementing cross-page posting is as simple as adding the PostBackUrl attribute to the ASP.NET button markup. The PostBackUrl property requires a string that represents the page to be posted to. The button does not require the OnClick attribute.
The page that receives the postback has access to the all the values contained in the originating page. We will take a look at three approaches to accessing this information.
In this scenario, there are two pages, Default1.aspx and Default2.aspx. Default1.aspx contains two ASP.NET controls; a text box and a button. The markup and code behind is shown in Listing 1. Also included in the listing is the definition of an interface that Default1 implements. The reason for this interface will become apparent a little later. The interface has a single function Name and as implemented in Default1 it returns the value in the text box. In addition, Default1, has a read only property that also returns the value of the text box.
Listing 1a: Default1.aspx
<form id="form1" runat="server">
<asp:TextBox ID="txtName" runat="server" >Foobar</asp:TextBox>
<asp:Button ID="bthCrossPagePostback" runat="server"
PostBackUrl="~/Default2.aspx" Text="Cross Page Postback">
</asp:Button>
</form>
Listing 1b: Default1.aspx.vb
Partial Class Default1
Inherits System.Web.UI.Page
Implements ICrossPage
Public Function Name() As String Implements ICrossPage.Name
Return txtName.Text
End Function
Public ReadOnly Property First() As String
Get
Return txtName.Text
End Get
End Property
End Class
Listing 1c: ICrossPage.vb
Public Interface ICrossPage
Function Name() As String
End Interface
The button has the PostBackUrl specified and has it's value set to Default2.aspx. When the user clicks this button the form will be submitted to Default2.aspx
Listing 2 shows the markup and code behind for the page Default2. The markup has three labels that will display the value of the text box from the originating page, Default1, one label for each of the three methods for accessing the text box's value.
Listing 2a: Default2.aspx
<form id="form1" runat="server">
<asp:Label ID="lblGreeting1" CssClass="lblGreeting" runat="server"></asp:Label><br /><br />
<asp:Label ID="lblGreeting2" CssClass="lblGreeting" runat="server"></asp:Label><br /><br />
<asp:Label ID="lblGreeting3" CssClass="lblGreeting" runat="server"></asp:Label>
</form>
Listing 2b: Default.aspx.vb
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Me.Load
If PreviousPage IsNot Nothing AndAlso PreviousPage.IsCrossPagePostBack Then
'Using PreviousPage.FindControl.
'Not strongly typed. What if you type the control name is wrong.
'No compile error.
'Tightly coupled to the page that did the cross page postback.
lblGreeting1.Text = "Using PreviousPage.FindControl: Hello " + _
CType(PreviousPage.FindControl("txtName"), TextBox).Text
'Using PreviousPage.First where First is a property.
'Strongly typed but is tightly coupled to the page that did the
'cross page postback.
'Needs this page directrive
'<%@ PreviousPageType VirtualPath="~/Default1.aspx" %>
lblGreeting2.Text = "Using PreviousPage.First: Hello " + _
PreviousPage.First
'Using PreviousPage that is cast to an interface.
'Strongly typed and is not coupled to the page where the cross page
'postback ocurred.
'All that is required is the page implemnent the interface.
lblGreeting3.Text = "Using ICrossPage.Name: Hello " + _
CType(PreviousPage, ICrossPage).Name
Else
lblGreeting1.Text = "If you want me to say hello then go to Default1 first."
End If
End Sub
The code behind populates each of the labels using three different approaches;
- Using FindControl: Here the FindControl method from the PreviousPage property is used to first instantiate a TextBox control and subsequently get the value of it. This approach has a major draw back; it is not strongly typed. What if the developer accidentally mistypes the name of the control? No compile time errors occur and we must check at runtime.
- Using a Property: In this case Default1, the originating page, has a property, First, that is used in Default2 to get the value of the text box. In order for this to work the PreviousPageType directive must be added to the Default2 page's markup. Unlike FindControl this approach is strongly typed and if the name of the property is mistyped we will get a compiler error. However, this approach suffers as it is tightly coupled to the originating page. What if we have two different pages each cross-page posting to the same page?
- Using an Interface: The last approach uses an interface. The originating page implements this interface and in the posted page we cast the PreviousPage to this interface. There is no need to add the PreviousPageType directive to the markup and since we are using an interface we are strongly typed. Strongly typed and loosely coupled, the best of both worlds!
Guess the movie
Yeah? I'll tell you what. Until I get back my five thousand dollars, you're gonna get more than you bargained for. I'm your goddamn partner.