Rob Garrett - Blogs

Welcome to Rob Garrett - Blogs Sign in | Join | Help
in Search
Google

Software/Technology Discussion

Software and Technology Tid-bits

IPostBackDataHandler and IPostBackEventHandler

I've been messing around with post back handler in ASP.NET today, and I found out a few points of interest.  Firstly, a description of the two interfaces used with server controls to handle post backs:

IPostBackEventHandler - Implemented by server controls that wish to handle post back events. The RaisePostBackEvent method is invoked by the framework when the control that implements this interface method is the source of a page post back - such as a submit button.  The RaisePostBackEvent method is expected to call an event delegate on the control, suck as Click.

IPostBackDataHandler - Implemented by server controls that wish to handle posted form data state changes. The LoadPostData method is invoked by the framework when the control that implements the interface method has posted some form data.  This method should compare the posted data (contained in a NameValueCollection, keyed with a passed unique post data key) with the data internal to the control, to see if the user changed the data on the page.  This method is expected to return true if the state of the data has changed.  The framework checks to return value of LoadPostData and calls the RaisePostDataChangedEvent method if the return value was true.  The RaisePostDataChangedEvent methods is expected to call a changed event delegate on the control.

Below is is the source code to a couple of server controls that I had implemented to test these interfaces. 

Point #1:  Initially both controls were not working.  After pulling out some hair, I figured out that each rendered control must output a "name" attribute with a unique value. Without this attribute the framework has no way of calling either the RaisePostBackEvent or LoadPostData methods on the correct control instance. Adding an ID field is not enough, for some reason ASP.NET insists on the "name" attribute.

Point #2: IPostBackDataHandler makes no sense on controls that do not change their state between page posts - duh.  Sounds obvious, but that still did not stop me spending 20 minutes trying to figure out why this interface was not working on my custom button control. 

Point #3: I wanted to know why the string argument passed to the RaisePostBackEvent method was null when I rendered my custom button as a regular HTML form submit button. Even though a simple submit button will cause a post back or sort - after all a post back is essentially a form submission - the framework will not interpret the form submit as a true post back without the __doPostBack JavaScript call.  This JavaScript method has the capacity to pass an argument to the framework during a form a post.  Adding this method to my code was a simple case of rendering the returned string from the GetPostBackEventReference method in an "onclick" attribute.

Point #4: When comparing posted data with that of the internal state of the data in the control, using LoadPostData, it helps if the control persists state of its own data in the first place.  For example, when persisting the text value in my custom text box I used the ViewState. Had I used a private member variable to store the internal text value, the persistence would have been lost for each post back; because a new instance of each control on the page is loaded for each page request.
Share this post: Email it! | bookmark it! | digg it! | reddit!
Published Tuesday, August 02, 2005 1:26 PM by Rob Garrett

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

Emad Omar said:

Point #1: Initially both controls were not working. After pulling out some hair, I figured out that each rendered control must output a "name" attribute with a unique value. Without this attribute the framework has no way of calling either the RaisePostBackEvent or LoadPostData methods on the correct control instance. Adding an ID field is not enough, for some reason ASP.NET insists on the "name" attribute.

The reason is
Upon postback, the page framework searches the posted content for values that match the UniqueIDs of server controls that implement
August 10, 2005 10:56 PM
 

Rob Garrett said:

Correct, but why is the "name" attribute required, surely you'd expect they would match against the "ID" attribute.

I understood that ASP.NET needs to something from the client to compare against controls in the tree, but was confused when I found out that MS chose the "name" attribute and not "ID".
August 11, 2005 12:24 AM
 

Daniel Teng said:

August 17, 2005 10:10 PM
 

Javier Troconis said:

Hi Rob,
I had the same problem u were having in your Section #1, and after having investigated what exactly is wrapped in the form upon submission I found the following :

----------------------------------------------------------------------------

17.13.3 Processing form data
When the user submits a form (e.g., by activating a submit button), the user agent processes it as follows.

Step one: Identify the successful controls
Step two: Build a form data set
A form data set is a sequence of control-name/current-value pairs constructed from successful controls

Step three: Encode the form data set
The form data set is then encoded according to the content type specified by the enctype attribute of the FORM element.

Step four: Submit the encoded form data set
Finally, the encoded data is sent to the processing agent designated by the action attribute using the protocol specified by the method attribute.

This specification does not specify all valid submission methods or content types that may be used with forms. However, HTML 4 user agents must support the established conventions in the following cases:

If the method is "get" and the action is an HTTP URI, the user agent takes the value of action, appends a `?' to it, then appends the form data set, encoded using the "application/x-www-form-urlencoded" content type. The user agent then traverses the link to this URI. In this scenario, form data are restricted to ASCII codes.
If the method is "post" and the action is an HTTP URI, the user agent conducts an HTTP "post" transaction using the value of the action attribute and a message created according to the content type specified by the enctype attribute.
For any other value of action or method, behavior is unspecified.

User agents should render the response from the HTTP "get" and "post" transactions.

17.13.2 Successful controls
A successful control is "valid" for submission. Every successful control has its control name paired with its current value as part of the submitted form data set. A successful control must be defined within a FORM element and must have a control name.

However:

Controls that are disabled cannot be successful.
If a form contains more than one submit button, only the activated submit button is successful.
All "on" checkboxes may be successful.
For radio buttons that share the same value of the name attribute, only the "on" radio button may be successful.
For menus, the control name is provided by a SELECT element and values are provided by OPTION elements. Only selected options may be successful. When no options are selected, the control is not successful and neither the name nor any values are submitted to the server when the form is submitted.
The current value of a file select is a list of one or more file names. Upon submission of the form, the contents of each file are submitted with the rest of the form data. The file contents are packaged according to the form's content type.
The current value of an object control is determined by the object's implementation.
If a control doesn't have a current value when the form is submitted, user agents are not required to treat it as a successful control.

Furthermore, user agents should not consider the following controls successful:

Reset buttons.
OBJECT elements whose declare attribute has been set.
Hidden controls and controls that are not rendered because of style sheet settings may still be successful. For example:

<FORM action="..." method="post">
<P>
<INPUT type="password" style="display:none"
name="invisible-password"
value="mypassword">
</FORM>

will still cause a value to be paired with the name "invisible-password" and submitted with the form.

------------------------------------------------------------------------------
That's the reason why the ID property is not enough, it has nothing to do with the framework itselt, it's just how the forms submission model works. For more info go to :
http://www.w3.org/TR/REC-html40/interact/forms.html#form-data-set

August 29, 2005 2:01 PM
 

Rob Garrett said:

Thanks for the very informative post Javier.
August 29, 2005 3:28 PM
 

John Tan said:

Hi Rob,

Just a point to add for #4. If I am not wrong, ViewStates are not why the values of the server controls persist during a postback. It is during the LoadPostData() method that the values are assigned. ViewStates only persist the PROPERTIES that are dynamically changed in the program codes but not the data in the control.

For those server controls like textboxes, dropdownlist boxes..etc in a page, even when viewstate is set to false for the page, the data values in the controls will still be persisted across postback but not the Properties.


John Tan
September 18, 2005 1:55 AM
 

Fabian said:

Great article, thanks.
April 24, 2006 12:13 PM

Leave a Comment

(required) 
(optional)
(required) 
Submit

Blurb


Head Shot
Rob Garrett is a British Expat living in Maryland USA. Rob is a trained software engineer and experienced in Windows .NET development.

Rob enjoys listening to Rock music, posting to blogs, driving in the country with the sunroof open, beer (not in conjunction with country driving) and spending time with his family.

This Blog

Syndication

Powered by Community Server, by Telligent Systems