4.2. Submitting a Form to a Different Page

Problem

You need to submit the information on one page—a form, for example—to another. You might want to do this to use one page to collect form data and a second page to process it.

Tip

The default operation for ASP.NET is to submit the form to the same page. Submitting the form to a different page—i.e., performing cross-page posting—requires some coding gymnastics in ASP.NET 1.x, explained in some detail in the first edition of the ASP.NET Cookbook:

  • Using the Server.Transfer method in a button click event handler in the code-behind of the first page to transfer control to a second page, after saving the contents of the first in session scope.

  • Using the Server.Transfer method in a button click event handler in the code-behind of the first page to transfer control, along with the form contents in the ViewState, to the second page.

In ASP.NET 2.0, however, performing cross-page posting is easier because you can now accomplish it by setting the PostBackUrl button property.

Solution

Use the cross-page posting functionality added to ASP.NET 2.0 to submit a form to a different page.

In the .aspx file of the first page, set to the URL of the desired page the PostBackUrl property of the button that will initiate the submission of the form to another page. No special code is required in the code-behind of the first page to support cross-page posting.

In the code-behind of the second page, use the .NET language of your choice to:

  1. Check to verify that page is being requested as a cross-page post from another page.

  2. Use the FindControl method of the PreviousPage property to get a reference to a control in the first page.

  3. Use the data from the control in the first page as required in the second page.

  4. Repeat the last two steps for each control in the first page that you need data for in the second page.

Examples 4-4, 4-5, 4-6, 4-7, 4-8 through 4-9 showthe .aspx and code-behind files for an application that implements this solution.

Discussion

The default operation for ASP.NET is to submit the form to the same page for processing. This operation is acceptable for most applications; however, the need may arise to submit the form to another page. This is much easier to do in ASP.NET 2.0 than in previous versions. In fact, prior to ASP.NET 2.0, submitting a form to another page required working around the system instead of with it.

In ASP.NET 2.0, the submission to another page is controlled by the PostBackURL property of the buttons on the form. This provides the ability to submit the form to different pages for each button.

	 <asp:Button ID="btnSubmit" runat="server"
					Text="Submit"
					PostBackUrl="~/CH04SubmitToAnother_SecondPageVB1.aspx" />

Warning

You cannot set the action attribute of the form element to cause the form to be submitted to another page. ASP.NET always changes the action to the URL of the page being displayed.

When the user clicks the submit button, ASP.NET executes a client-side JavaScript method that performs the submission to the second page, passing the information necessary for the second page to determine if the request is the result of a cross-page post, as well as the data to rehydrate the page object for the first page.

You can determine if a page is being requested as a result of a cross-page post by checking if the PreviousPage property of the Page object is null (Nothing in VB):


	If (IsNothing(Page.PreviousPage)) Then
		'page is not being accessed by a cross-page postback

	Else
		'page is being accessed by a cross-page postback 

	End If

	if (Page.PreviousPage == null)
	{
	  // page is not being accessed by a cross-page postback
	}
	else
	{
	  // page is being accessed by a cross-page post-back
	}

Warning

The first time you access the PreviousPage property, ASP.NET rehydrates the page object for the first page. As part of the rehydration, all events up to LoadComplete are fired. This includes the button click event for the submit button that was clicked. If your code contains an event handler for the click event for the buttons used to submit to another page, this code will be executed.

By accessing the PreviousPage property, your code can access the content of the controls on the first page. Since the PreviousPage property is of type Page, you cannot directly access the controls. You have to use the FindControls method to get a reference to the desired control and then access the data in the control.


	get the page content control
	'NOTE: This is required since a master page is being used and the
	'	   controls that contain the data needed here are within it
	pageContent = CType(Page.PreviousPage.Form.FindControl("PageBody"), _
						ContentPlaceHolder)
	'get the first name data from the first page and set the label
	'on this page
	tBox = CType(pageContent.FindControl("txtFirstName"), _
							TextBox)
	lblFirstName.Text = tBox.Text
	

	// get the page content control
	// NOTE: This is required since a master page is being used and the
	//		 controls that contain the data needed here are within it
	pageContent = (ContentPlaceHolder)
				  (Page.PreviousPage.Form.FindControl("PageBody"));

   // get the first name data from the first page and set the label
   // on this page
   tBox = (TextBox)(pageContent.FindControl("txtFirstName"));
   lblFirstName.Text = tBox.Text;

Tip

If the control you are accessing is contained within another control, such as a template or a content placeholder, you need to use FindControl to get a reference to the container first and then use FindControl again to get a reference to the control containing your data.

Though the solution shown above works fine and is acceptable in most applications, it has two problems. First, you must have knowledge of the structure of the first page to get a reference to the desired controls in the second (described above). This can become complicated if the controls on the first page are embedded in multiple layers of control containers. Second, the access to the controls is not strongly typed, requiring you to cast the control type for access. If the control type changes on the first page, the code in the second page must also be changed.

Another solution that eliminates these problems is to add public properties to the code-behind of the first page that expose the data in the controls that you need in the second page:

	
	'''********************************************************************
	''' <summary>
	''' This routine provides the ability to get/set the firstName property
	''' </summary>
	Public Property firstName() As String
		Get
		  Return (txtFirstName.Text)
		End Get
		Set(ByVal value As String)
			txtFirstName.Text = value
		End Set
	End Property

	'''********************************************************************
	''' <summary>
	''' This routine provides the ability to get/set the lastName property
	''' </summary>
	Public Property lastName() As String
		Get
		   Return (txtLastName.Text)
		End Get
		Set(ByVal value As String)
	txtLastName.Text = value
		End Set
	End Property

	'''*******************************************************************
	 ''' <summary>
	 ''' This routine provides the ability to get/set the age property
	 ''' </summary>
	 Public Property age() As String
		Get
		  Return (txtAge.Text)
		End Get
		Set(ByVal value As String)
	txtAge.Text = value
		  End Set
		End Property
	
	///********************************************************************
	/// <summary>
	/// This routine provides the ability to get/set the firstName property
	/// </summary>
	public String firstName
	{
	  get
	  {
		 return (txtFirstName.Text);
	  }
	  set
	  {
		 txtFirstName.Text = value;
	  }
	 } // firstName
	  
	 ///*******************************************************************
	 /// <summary>
	 /// This routine provides the ability to get/set the lastName property
	 /// </summary>
	 public String lastName
	 {
		get
		{
			return (txtLastName.Text);
		}
		set
		{
		   txtLastName.Text = value;
		}
	  } // lastName

	 ///*******************************************************************
	 /// <summary>
	 /// This routine provides the ability to get/set the age property
	 /// </summary>
	 public String age
	 {
		get
		{
			return (txtAge.Text);
		}
		set
		{
			txtAge.Text = value;
		}
	 } // age

In the .aspx file of the second page, add the PreviousPageType directive to the top of the file with the VirtualPath attribute set to the URL of the first page:

	<%@ Page Language="VB" MasterPageFile="~/ASPNetCookbookVB.master"
	  AutoEventWireup="false"
	  CodeFile="CH04SubmitToAnother_SecondPageVB2.aspx.vb"
	  Inherits="ASPNetCookbook.VBExamples.CH04SubmitToAnother_SecondPageVB2"
	  Title="Form Submission To Another Page - Second Page - Approach 2" %>
    <%@ PreviousPageType VirtualPath="~/CH04SubmitToAnother_FirstPageVB2.aspx" %>

Tip

References to pages, images, and other resources are typically prefaced with “~/”, which is used to indicate the root folder of the web application.

In the code-behind of the second page, define a variable of the type of the first page and set its value to the PreviousPage property of the Page object:

	
	Dim prevPage As CH04SubmitToAnother_FirstPageVB2
	
	'get a strongly type reference to the previous page
	prevPage = CType(Page.PreviousPage, _
					CH04SubmitToAnother_FirstPageVB2)

    	
	CH04SubmitToAnother_FirstPageCS2 prevPage;

	// get a strongly type reference to the previous page
	prevPage = (CH04SubmitToAnother_FirstPageCS2)(Page.PreviousPage);

With the strongly typed reference to the first page, you can directly access the properties you added to access the required data:

	
	lblFirstName.Text = prevPage.firstName
	lblLastName.Text = prevPage.lastName
	lblAge.Text = prevPage.age

	
	lblFirstName.Text = prevPage.firstName;
	lblLastName.Text = prevPage.lastName;
	lblAge.Text = prevPage.age;

This second solution is cleaner and less likely to break when the code is changed during future maintenance operations. It does require a little more planning and coding but it is worth the effort.

See Also

Search ASP.NET 2.0 Internals in the MSDN Library.

Example 4-4. Submitting a form to another page—first page (.aspx)

<%@ Page Language="VB" MasterPageFile="~/ASPNetCookbookVB.master"
  AutoEventWireup="false"
  CodeFile="CH04SubmitToAnother_FirstPageVB1.aspx.vb"
  Inherits="ASPNetCookbook.VBExamples.CH04SubmitToAnother_FirstPageVB1"
  Title="Form Submission To Another Page - Approach 1" %>
<asp:Content ID="pageBody" Runat="server" ContentPlaceHolderID="PageBody">
   <div align="center" class="pageHeading">
      Form Submission To Another Page - Approach 1 (VB)
   </div>
   <table width="50%" align="center" border="0">
   <tr>
     <td class="labelText">First Name: </td>
	 <td>
	    <asp:TextBox ID="txtFirstName" Runat="server"
						Columns="30" CssClass="LabelText" />
	</td>
  </tr>
  <tr>
     <td class="labelText">Last Name: </td>
	 <td>
	 <asp:TextBox ID="txtLastName" Runat="server"
					Columns="30" CssClass="LabelText" />
	</td>
  </tr>
  <tr>
	 <td class="labelText">Age: </td>
	 <td>
	   <asp:TextBox ID="txtAge" Runat="server"
						Columns="30" CssClass="LabelText" />
	</td>
  </tr>
  <tr>
     <td align="center" colspan="2">
	   <br/>
	   <asp:Button ID="btnSubmit" runat="server"
					  Text="Submit"
					  PostBackUrl="~/CH04SubmitToAnother_SecondPageVB1.aspx" />

	  </td>
	</tr>
  </table>
</asp:Content>

Example 4-5. Submitting a form to another page—first page (.vb)

Option Explicit On
Option Strict On

Namespace ASPNetCookbook.VBExamples
	''' <summary>
	''' This class provides the code behind for
	''' CH04SubmitToAnother_FirstPageVB1.aspx
	''' </summary>
	Partial Class CH04SubmitToAnother_FirstPageVB1
		Inherits System.Web.UI.Page
		'''****************************************************************
		''' <summary>
		''' This routine provides the event handler for the page load event. It
		''' is responsible for initializing the controls on the page.
		''' </summary>
		'''
		''' <param name="sender">Set to the sender of the event</param>
		''' <param name="e">Set to the event arguments</param>
		Protected Sub Page_Load(ByVal sender As Object, _
							   ByVal e As System.EventArgs) Handles Me.Load
	    End Sub 'Page_Load
    End Class 'CH04SubmitToAnother_FirstPageVB1
End Namespace

Example 4-6. Submitting a form to another page—first page (.cs)

using System;
namespace ASPNetCookbook.CSExamples
{
   /// <summary>
   /// This class provides the code behind for
   /// CH04SubmitToAnother_FirstPageCS1.aspx
   /// </summary>
   public partial class CH04SubmitToAnother_FirstPageCS1 : System.Web.UI.Page
   {
    ///*******************************************************************
	/// <summary>
    /// This routine provides the event handler for the page load event.
	/// It is responsible for initializing the controls on the page.
	/// </summary>
	///
	/// <param name="sender">Set to the sender of the event</param>
	/// <param name="e">Set to the event arguments</param>
	protected void Page_Load(object sender, EventArgs e)
    {
	} // Page_Load
  } // CH04SubmitToAnother_FirstPageCS1
}

Example 4-7. Submitting a form to another page—second page (.aspx)

<%@ Page Language="VB" MasterPageFile="~/ASPNetCookbookVB.master"
   AutoEventWireup="false"
   CodeFile="CH04SubmitToAnother_SecondPageVB1.aspx.vb"
   Inherits="ASPNetCookbook.VBExamples.CH04SubmitToAnother_SecondPageVB1"
   Title="Form Submission To Another Page - Second Page - Approach 1" %>
<asp:Content ID="pageBody" Runat="server" ContentPlaceHolderID="PageBody">
    <div align="center" class="pageHeading">
	   Form Submission To Another Page - Approach 1 (VB)
	</div>
	<table width="50%" align="center" border="0">
	  <tr>
	    <td colspan="2" align="center" class="pageHeading">
		  Data Submitted From Previous Page
		</td>
	  </tr>
	  <tr>
	     <td class="labelText">First Name: </td>
		 <td class="labelText">
			<asp:Label ID="lblFirstName" Runat="server" />
		 </td>
 
		 </tr>
		 <tr>
			<td class="labelText">Last Name: </td>
			<td class="labelText">
				<asp:Label id="lblLastName" Runat="server" />
			</td>
		</tr>
		<tr>
			<td class="labelText">Age: </td>
			<td class="labelText">
				<asp:Label ID="lblAge" Runat="server" />
			</td>
		</tr>
		<tr>
			<td colspan="2">&nbsp;</td>
		</tr>
		<tr>
		    <td class="labelText">Page Access Method: </td>
			<td class="labelText">
				<asp:Label ID="lblPageAccessMethod" Runat="server" />
			</td>
		</tr>
	</table>
</asp:Content>

Example 4-8. Submitting a form to another page—second page (.vb)

Option Explicit On
Option Strict On

Imports System.Web.UI.WebControls

Namespace ASPNetCookbook.VBExamples
   ''' <summary>
   ''' This class provides the code behind for
   ''' CH04SubmitToAnother_SecondPageVB1.aspx
   ''' </summary> Partial Class CH04SubmitToAnother_SecondPageVB1
		Inherits System.Web.UI.Page
		'''******************************************************************
		''' <summary>
		''' This routine provides the event handler for the page load event. It
		''' is responsible for initializing the controls on the page.
		''' </summary>
		'''
		''' <param name="sender">Set to the sender of the event</param>
		''' <param name="e">Set to the event arguments</param>
		Protected Sub Page_Load(ByVal sender As Object, _
								ByVal e As System.EventArgs) Handles Me.Load
			Dim tBox As TextBox
			Dim pageContent As ContentPlaceHolder 
			'check to see how the page is being accessed
			If (IsNothing(Page.PreviousPage)) Then
			'page is not being accessed by cross-page post so check to if
			'it is being accessed via self post-back
			If (Page.IsPostBack) Then
				'page is being accessed by a post-back from itself
				lblPageAccessMethod.Text = "Page was accessed via post-back"
			Else
				'page is being accessed directly
				lblPageAccessMethod.Text = "Page was accessed directly"
			End If
		Else
			'page is being accessed by a cross-page post-back
			lblPageAccessMethod.Text = "Page was accessed via cross-page post-back"

			'get the page content control
			'NOTE: This is required since a master page is being used and the
			'        controls that contain the data needed here are within it
			pageContent = CType(Page.PreviousPage.Form.FindControl("PageBody"), _
									ContentPlaceHolder)
									
			'get the first name data from the first page and set the label
			'on this page
			tBox = CType(pageContent.FindControl("txtFirstName"), _
						  TextBox)
			lblFirstName.Text = tBox.Text
	 
			'get the last name data from the first page and set the label
			'on this page
			tBox = CType(pageContent.FindControl("txtLastName"), _
						 TextBox)
			lblLastName.Text = tBox.Text
	 
			'get the age data from the first page and set the label
			'on this page
			tBox = CType(pageContent.FindControl("txtAge"), _
						TextBox)
			lblAge.Text = tBox.Text
		  End If
		End Sub 'Page_Load
	End Class 'CH04SubmitToAnother_SecondPageVB1
End Namespace

Example 4-9. Submitting a form to another page—second page (.cs)

using System;
using System.Web.UI.WebControls;

namespace ASPNetCookbook.CSExamples
{
  /// <summary>
  /// This class provides the code behind for
  /// CH04SubmitToAnother_SecondPageCS1.aspx
 /// </summary>
 public partial class CH04SubmitToAnother_SecondPageCS1 : System.Web.UI.Page
 {
	///*********************************************************************
	/// <summary>
	/// This routine provides the event handler for the page load event.	
	/// It is responsible for initializing the controls on the page.
	/// </summary>
	///
	/// <param name="sender">Set to the sender of the event</param>
	/// <param name="e">Set to the event arguments</param>
	protected void Page_Load(object sender, EventArgs e)
	{
		TextBox tBox;
		ContentPlaceHolder pageContent;
	 
	 // check to see how the page is being accessed
	 if (Page.PreviousPage == null)
	 {
	    // page is not being accessed by cross-page post so check to if
		// it is being accessed via self post-back
		if (Page.IsPostBack)
		{
		  // page is being accessed by a post-back from itself
		  lblPageAccessMethod.Text = "Page was accessed via post-back";
		}
		else
		{
		  // page is being accessed directly
		  lblPageAccessMethod.Text = "Page was accessed directly";
        }
	  }
	  else
	  {
	     // page is being accessed by a cross-page post-back
		 lblPageAccessMethod.Text = "Page was accessed via cross-page post-back";

		 // get the page content control
		 // NOTE: This is required since a master page is being used and the
		 //     controls that contain the data needed here are within it
		 pageContent = (ContentPlaceHolder)
					   (Page.PreviousPage.Form.FindControl("PageBody"));

		 // get the first name data from the first page and set the label
		 // on this page
		 tBox = (TextBox)(pageContent.FindControl("txtFirstName"));
		 lblFirstName.Text = tBox.Text;
		 
		 // get the last name data from the first page and set the label
		 // on this page
		 tBox = (TextBox)(pageContent.FindControl("txtLastName"));
		 lblLastName.Text = tBox.Text;
		 
		 // get the age data from the first page and set the label
		 // on this page
		 tBox = (TextBox)(pageContent.FindControl("txtAge"));
		 lblAge.Text = tBox.Text;
	  }
	}  // Page_Load
  } // CH04SubmitToAnother_SecondPageCS1
}

Get ASP.NET 2.0 Cookbook, 2nd Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.