Understanding what Page.RegisterRequiresPostBack does

I recently received a comment in my Truly Understanding ViewState article about the "ArrayList of controls in the control hierarchy that need to be explicitly invoked by the page class during the raise postback event stage of the life cycle." Such is the 3rd entry in the master Triplet that makes up ViewState as a whole.

It was a very excellent question, and in some quick searches I don't see any really clear topics dedicated to answering it, so I decided to answer it with a blog post rather than bury it at the bottom of 100 comments. You can read the comment here.

 

Page.RegisterRequiresPostBack

To understand why this method is needed, lets walk through what happens when you use an ImageButton.

When you click on an html element of the <input type=image> variety, what is added to the form collection sent to the server is not what a normal button sends. A normal button sends the key/value pair "id=value". But an image submit sends "id.x=##&id.y=##". It sends 2 values, the x and y coordinates of the location of the image you clicked.

This means the KEY of the submission will not match the ID of the control. Normally, ASP.NET matches keys to their control IDs, and is able to find the control directly with FindControl() (which also has the indirect effect of calling EnsureChildControls). But it won't find a control named "id.x" or "id.y", so that ImageButton will never be notified of the postback data it generated.

All is not lost! RegisterRequiresPostBack comes the rescue. It tells asp.net to notify the control of postback data regardless of whether the form collection contains an entry for it. ImageButton can now happily look for "id.x" and "id.y" in the form data, and raise its click event if it is found.

Now why is there a list of controls that call RegisterRequiresPostBack in ViewState of all places? Because when you call RegisterRequiresPostBack, you're doing so for the next request not the current one. You're saying, "when what I'm rendering right now is posted back, I want to be notified." So ASP.NET needs to maintain the list of controls in ViewState so it can do so on the next request.

Some people have complained that even when they disable ViewState for the entire page, they see ViewState in their page. This is one of the reasons for that. It is simply required for the controls to function, it cannot be turned off.

The humble CheckBox

Another control the calls RegisterRequiresPostBack is the humble CheckBox control. When you post a form, any checked checkboxes are added to the form collection with "id=value". However, and quite unfortunately if you ask me, unchecked checkboxes add NOTHING to the form collection.

Ok -- so a CheckBox knows it is checked if its post data key exists, and unchecked if it is missing, right? Nope, sorry, that simply won't do. What would happen to a checkbox that is first created during a postback? For example, a checkbox within a databound control that has just been databound? How does that CheckBox know whether it is unchecked or has just been born into the world, err, page? The only way to know the difference is RegisterRequiresPostBack. If not for that, all checkboxes first created during postbacks would always start off unchecked, even if they were databound or declared to be checked.

Homework

Open up reflector and find the Page.RegisterRequiresPostBack method. Use the analyzer to find all the controls that call it. Try to understand why each of them needs it. I assure you, they all have good but distinct reasons.

10 Comments

  • Ahhh the good ol days of simple classic ASP - oh how I miss thee..

  • Well it was simpler in those days... but I don't miss them that's for sure.

  • Hi Dave!
    Lots of developers don't like to use postback events of controls and prefer finding postback control through Page.Request.Form[Page.postEventSourceID] (exception is Button with UseSubmitBehavior=true, but they set it to false). As for me, I don't like this coding way at all.
    And what do you think about it?

  • Alexander -- that may work in simple scenarios but not complex ones. The fact the form collection contains that key doesn't mean that is the control's value. Rebinding a grid results in elements with the same name for example, but they have different values.

    If it solves a problem and it works reliably in your scenario then fine, but I'd avoid it if possible. There's probably a better way to solve the issue you're trying to work around.

  • hey dave,
    It was very quick .. Thank you so much.. :)

  • Hi dave ,
    I have tried to summarize what ProcessPostData method does.
    ProcessPostData method restore User Posted value into controls and raised the changed event if control value has been &nbsp;
    changed due to posted value.
    ProcessPostData &nbsp;method will process all those controls that it received through &nbsp;
    1) Forms collection
    2) Controls collection that exists in 3rd Item of First Triplet of ViewState (refer ViewState structure) .This control &nbsp;
    collection is populated for Web controls like Image button, which is internally registered using &nbsp;Page.RegisterRequiresPostBack method.
    So Can we conclude that the controls that are explicitly registered using Page.RegisterRequiresPostBack method will find &nbsp;
    its way in Viewstate(3rd item of first triplet) irrespective of whether User has enabled viewstate ? &nbsp;

  • If the checkbox requires this functionality, why then does the textbox not need it?

  • mhildreth -- because, the value of a textbox is always in the form collection when it is posted, even if the value is blank.

  • Thanks for the quire response - The reason I was asking was when a control containing the TextBox has it's Visible property set to false, the TextBox value is not posted, and therefore raises the TextChanged event and unforunately sets the TextBox's Text value to and empty string. I've worked around this by inheriting from the TextBox and overriding the LoadPostData method as follows:

    protected override bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
    {
    Page.ClientScript.ValidateEvent(postDataKey);

    // if no value was posted, then don't set the text to null
    if (Array.IndexOf(postCollection.AllKeys, postDataKey) > -1)
    {
    string CurrentText = this.Text;
    string PostedValue = postCollection[postDataKey];
    if (!this.ReadOnly && !CurrentText.Equals(PostedValue, StringComparison.Ordinal))
    {
    this.Text = PostedValue;
    return true;
    }
    }

    return false;
    }

    Are there any issues that I should be aware of when doing this?

  • If the TextBox was not visible when the form was posted then it wont have an entry in the form collection and therefore its LoadPostData method would not be called by the framework. I suspect you have a different issue at hand. Test it out with just a textbox and a button on the form and I'm sure you'll see it does not get set to empty. If you had ViewState disabled, then it would empty out, because ViewState is how its value is maintained when it is invisible.

Comments have been disabled for this content.