Tuesday, January 1, 2008

Access Previous Page's Controls Using Cross Page Postback

How to access previous page's controls

Before Asp.Net 2.0 was introduced, accessing the previous page's controls from a given page was a tricky affair. You had to use nice but not so right features like Session, HttpContext, even cookies in some cases, to persist relevant information from one page to another. Session is useful when you have to persist a bunch of data across the user's session, but it is not suitable for passing random values between pages. The primary reason for this being that as your application gets more and more complex, the Session state could become cluttered and confusing because of similarly named session values, and could easily become a maintainence nightmare. After a period of time, you would not remember what Session state variables you used to pass values between which pages.

Asp.Net 2.0 comes with a very handy feature called the PreviousPage property. This is a public property of the Page class, and refers to the PreviousPage instance. Using this property, you can access the previous page's public properties. You can also access the previous page's controls using the FindControll method.

Let us take an example. Suppose we have the following web page, that has a simple textbox and a button. Note that the button's PostBackUrl property is set to another page, meaning that when the button is clicked, the current webform will post back to the PostBackUrl page (If you are not clear with cross page HTTP postbacks, look at this post).

    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "">

    <html xmlns="" >
    <head runat="server">
     <title>Untitled Page</title>
     <form id="form1" runat="server">
      <asp:Button ID="Button1" runat="server" PostBackUrl="~/Default2.aspx" Text="Button" />
      <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox></div>

What happens here is that Asp.Net looks at the PostBackUrl property of the button and understands that form needs to be submitted to another form. To achieve this, it emits a javascript function called WebForm_DoPostBackWithOptions that makes sure that the form is correctly submitted to another page. To further understand what I am saying, look at the source for your page (right click, view source). Here's what our button looks like in actual HTML :

     <input type="submit" name="Button1" value="Button" onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;Button1&quot;, &quot;&quot;, false, &quot;&quot;, &quot;Default2.aspx&quot;, false, false))" id="Button1" />

Now to understand fully how Asp.Net posts back to another form, we must first understand the mechanism Asp.Net uses to postback a form. If you carefully look at the above HTML source for the button, you will see that onclick, the button calls a javascript method called [WebForm_DoPostBackWithOptions]. This method comes out of the box with Asp.Net. To view it's contents, we need to find the Javascript file to which the method belongs to. If you glance at the HTML source of the page, you will see that there is a file called WebResource.axd included with your page :

    <script src="/WebSites1/WebResource.axd?d=wKUbMd8wFV3uZ8WZXaQryA2&amp;t=633245101798773778" type="text/javascript"></script>

To look at the actual webresource.axd, do this : Internet Explorer --> Tools --> Settings --> View Files. This will open up a folder, where there will be one or many instances of WebResource.axd. This is a standard Javascript file that contains common Asp.Net page related functionality.

You can go through the WebForm_DoPostBackWithOptions method in the file to understand the exact mechanism for postback. Specifically, note how the [action] property of the webform is changed to the other page. Upon form submission, Asp.Net posts the form to the other page, instead of doing a normal page postback to itself. Upon postback, even though the form posts to another page, the original page's page lifecycle executes upto the [OnLoadComplete] event. After that, Asp.Net transfers the page execution to the other page (I assume it does a Server.Transfer), and also sets the IsCrossPagePostback property for the next page. Once on the other page, it continues the normal page lifecycle of the other page, and renders on page.

All this can get a bit confusing, so let's go through the entire thing again :

1. The first page is Page_A. User clicks a button that has the PostBackURL property set to Page_B.

2. Upon the button click, the [WebForm_DoPostBackWithOptions] javascript method is called. This method is part of the WebResource.axd file.

3. This method sets the form's [action] property to the Page_B, and posts the form.

4. Page_A page lifecycle starts executing upto the OnLoadComplete event, after which Asp.Net transfers execution to the Page_B, also setting Page_B's [IsCrossPagePostback] property on the way. Also, Page_B's PreviousPage property is set to the Page instance object of Page_A. (You know that each page is compiled into an object that derives from System.Web.UI.Page, right. That's the Page Instance Object I was referring to.)

5. Page_B page now starts executing it's normal page lifecycle. Since PreviousPage refers to the instance of Page_A, you can access any public property on the page, any web control on the page, infact, you can call public methods on Page_A.

6. Page_B now executes its normal page lifecycle, accessing public properties/methods/controls on Page_A if required, and renders it's HTML.

I would have loved to explain how I figured out all this internal stuff about Cross Page postbacks, but can't for "lack of space" (it's more like "lack of desire to keep on drooling on the same thing" ;) ), but you can take a look at the source code right here I used to figure out what I did. You can put this code into Debug, setting breakpoints at various key methods to understand how it works.

An oh yes, do remember that you can access 1. Public Properties, 2. Page Controls, 3. Static Variables, 4. Call public methods, using the PreviousPage property. So go ahead and play around with this powerful feature, and find interesting ways to use it in your Asp.Net WebApps.