Cross-page posting in ASP.NET: read the previous page's controls
Normally a Web Forms page posts back to itself. With cross-page posting, a button sends the form to a different page, which can then read the first page's controls through PreviousPage. It is a tidy way to build a search form whose results live on another page, without putting everything in the URL.
The source page
<%-- Search.aspx --%>
<asp:TextBox ID="txtTerm" runat="server" />
<asp:DropDownList ID="ddlScope" runat="server">
<asp:ListItem Value="all">Everything</asp:ListItem>
<asp:ListItem Value="docs">Documents only</asp:ListItem>
</asp:DropDownList>
<asp:Button ID="btnSearch" runat="server" Text="Search" PostBackUrl="~/Results.aspx" />
Expose the values through public properties in the code-behind, so the target page does not need to know control ids:
public partial class Search : Page
{
public string Term => txtTerm.Text.Trim();
public string Scope => ddlScope.SelectedValue;
}
The target page, strongly typed
<%@ Page Language="C#" CodeBehind="Results.aspx.cs" Inherits="Demo.Results" %>
<%@ PreviousPageType VirtualPath="~/Search.aspx" %>
public partial class Results : Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (PreviousPage != null && PreviousPage.IsCrossPagePostBack)
{
string term = PreviousPage.Term; // typed as Demo.Search thanks to @PreviousPageType
string scope = PreviousPage.Scope;
lblInfo.Text = "Results for " + Server.HtmlEncode(term);
RunSearch(term, scope);
}
else if (!IsPostBack)
{
Response.Redirect("~/Search.aspx", false);
Context.ApplicationInstance.CompleteRequest();
}
}
}
When you read PreviousPage, ASP.NET creates an instance of Search, runs its life cycle up to LoadComplete with the posted data, and hands it to you. Its controls contain the values the user submitted. Validation has run on the source page too, so you can check PreviousPage.IsValid.
Without the directive: FindControl
if (PreviousPage != null)
{
var box = (TextBox)PreviousPage.FindControl("txtTerm");
string term = box?.Text;
}
If the source uses a master page, the controls sit inside a ContentPlaceHolder, and PreviousPage.FindControl will not find them directly: look them up through PreviousPage.Master.FindControl("MainContent").FindControl("txtTerm"). Public properties avoid this fragility.
Comparison
| Technique | URL in the browser | Data |
|---|---|---|
| Cross-page post | The target page | Full form posted to the target |
Server.Transfer | Still the source page | PreviousPage also available, no new request |
| Query string | Target page with parameters, bookmarkable | A few short values |
| Session | Any | Kept server-side across many requests |
A cross-page post is a POST: refreshing the results page asks the browser to resend the form, and the results cannot be bookmarked. For a search page that users share, the query string is usually better.
Common mistakes
- Reading
PreviousPagewhen the user arrives by a link or a bookmark: it isnull. Always check it, as above. - Forgetting that the source page's
Page_Loadruns again to buildPreviousPage: expensive work there, such as database queries, runs twice. Guard it withif (!IsPostBack)or move it to event handlers. - Expecting
IsPostBackto be true on the target page: for a cross-page post it is false;PreviousPage.IsCrossPagePostBackis true.
Official documentation
- Microsoft Learn: Page.PreviousPage, Page.IsCrossPagePostBack, Button.PostBackUrl
- Microsoft Learn: Cross-page posting in ASP.NET Web Pages