Saturday, August 25, 2012

Hidden LoadPostData in Page Life Cycle for Dynamic Controls



One of the most basic things that an ASP.NET programmer must be familiar about is the page life cycle. This is very well documented in several places, but I always refer back to MSDN's beautifully illustrated chart almost halfway through the page here.

While debugging an application that dynamically adds controls to the web page, I found a bug caused by events not firing in the expected sequence. Basically, we used a custom control that assumed that the LoadPostData event data is always fired before the Load event. As I will explain later, this is not always true. I modified the page life cycle diagram, with my addition highlighted with a green background to add a very important event not shown in the original.

Page Life Cycle Diagram Showing Second LoadPostData Event

The problem was originally caused by my application dynamically adding a control during the page load event. What this means is that during the postback's first LoadPostData event, the control has not been added to the control tree yet. This might imply that during postback, controls that are dynamically added during the Load (or later) events will not receive a LoadPostBack event. In reality, a list of all control ID's in the viewstate that was not found during the first LoadPostData is automatically saved. After the load events are completed, ANOTHER round of LoadPostData event, highlighted in green above, is fired using this list. This is somewhat mentioned under the section Catch-Up Events For Added Controls, but is not explained in any useful detail.

Going back to my original problem, the custom control in question would crash when the LoadPostData event is fired after the Load event had already fired. This means that when you're writing your own custom controls, you should not assume that the LoadPostData event is always fired before the Load event. Knowing this, I was able to make changes to fix the bug in the custom control. To follow best practices, I also overrode the CreateChildControls method and moved all code that added controls to the form here. Then I called the EnsureChildControls method during the page load event.

1 comment: