The first method that executes when a page is requested is always the constructor. You can initialize many of the custom properties or objects in the page at this time, although there are a few limitations since the page hasn’t fully initialized yet. In particular, you will have to use the HttpContext.Current object to access the Request QueryString, Form, and Cookies collections, along with the Cache object. However, there is no way to access the Session collection within the constructor.
The next method that executes is the AddParsedSubObject method, which actually adds all the individual controls that make up a page into the control collection tree. This method is typically overridden by some of the advanced page template solutions in order to add the page contents into a particular control in the page template. This method is recursively called on all children controls for each page control, and each of these controls is initialized at this time, starting with the innermost.
The next method that executes is the DeterminePostBackMode method of the page class. This method allows you to affect the value of IsPostBack and all the related events, which might be useful if you need to load ViewState from a database for a redirect, since we will see that ViewState is only restored when IsPostBack is actually true. Just return null to force non-PostBack and return Request.Form to force a PostBack. This is not recommended, except in special cases, since it affects other events too.
The page’s OnInit method is executed next, which is typically the first method used. By the time this occurs, all the controls defined in your page will be initialized, which means that all the original values specified in the aspx page will be applied. However, ViewState and any posted values will not have been applied to controls yet, so anything that changed as a result of the code or user will not yet be restored. This is usually the best place to create, and recreate, any dynamic controls used.
Restore and Load
The next method, LoadPageStateFromPersistenceMedium, only executes for PostBacks. This method is overridden when you have altered how the page’s ViewState was saved, later in the SavePageStateToPersistenceMedium, when using Session or Custom Stores. The default implementation assumes ViewState is a Base64 encoded hidden form field, but this can be changed in these two methods using code found in this related article. Note that this method does not actually restore ViewState to the page or its controls.
After ViewState is retrieved, the next method, LoadViewState, restores it to the page, and then recursively to each control and their children, but again only on PostBacks. After this executes, each control will now be restored to the state it was last time, but user posted values will still not be applied, since this is not part of ViewState. The best use of this method is to restore any dynamic controls you created in events, based on values you must manually save in ViewState, which is now available to use.
The next method, ProcessPostData, only executes for PostBacks, and it is not able to be overridden, since it is a private method implemented by the base page class. This method finally restores the user’s posted form values by matching up controls with the names of the values, which means your page will finally be fully restored. The only catch is that dynamic controls must be created prior to this page method. This is also the method that records changes in values for the changed events later.
The page’s OnLoad method is executed next, which is typically used for most code, since this is the first place in the page lifecycle that all values are restored. Most code checks the value of IsPostBack to avoid unnecessarily resetting state. You may also wish to call Validate and check the value of IsValid in this method. You can also create dynamic controls in this method, and all the control’s methods will be executed to catch up, including ViewState, but posted values would not be.
The next method, ProcessPostData, is actually a second pass of the earlier method, which still only executes for PostBacks and is not overridable since private method. This second pass always seems a little odd when you first notice it in the page trace, but it occurs because dynamic controls recreated in OnLoad need their posted values. Any controls that are dynamically created after this method, while having ViewState restored, will not get their posted values nor be able to trigger any changed events.
The next method, RaiseChangedEvents, also occurs only for PostBacks, and it too is a private method that is implemented in the base page class that cannot be overridden. This is the time in the page lifecycle that the changed events are actually raised, based on the differences that ProcessPostData noted before and after posted values. You may also want to call Validate and check the value of IsValid, if not already. There is no guarantee about the order that multiple changed events will be raised.
The page’s OnPreRender method is executed next, which is typically the last chance to affect the page and its controls before it is rendered to the client’s browser. You can also create dynamic controls in this method, and all the control’s methods will be executed to catch up, including ViewState, but the earlier private methods will not receive another pass, meaning no posted values are restored and no events. This is a good place to catch a PostBack without an event due to the bug noted in IE.
Save and Render
The next method that executes, regardless whether PostBack or not, is SaveViewState which recursively runs for each control and their children, to create the ViewState. ViewState basically stores any property values that are different from the original values that are defined in the aspx page, whether changed in the code or by the user. Note that control values are saved according to their location in the control tree, so ViewState can get corrupted if dynamic controls are later added in wrong positions.
The next method, SavePageStateToPersistenceMedium, actually saves the page ViewState. This method is overridden, along with LoadPageStateFromPersistenceMedium, to save the ViewState either to Session or a Custom Store, instead of using the hidden field. This is useful for low bandwidth cases, and Session is the default for Mobile Pages. See the code found in this related article for details of using these two methods, and note that a bug in ASP.NET requires a __VIEWSTATE field to be sent, even if empty.
The page’s Render method is executed next, which recursively runs for each control and their children, to actually create and send the resulting html to the browser. This method is used in some page template solutions to add common headers and footers to the page without using server controls, which always have a little extra overhead. Note that changes made here must be pure html, since controls are done at this time. You can capture the html output using StringBuilder, StringWriter, and HtmlTextWriter.
The very last method to be executed is OnUnload, which also calls the Dispose method. This method gives you a chance to cleanup any unmanaged resources used in the page, typically things like closing any open files or database connections open earlier. Note that this method runs only after the page has been sent to the client’s browser, so it will only affect server objects, and it will not show up in a trace of the page. And that’s the page lifecycle — everything runs all over again with each new request.
Listing 1: Page Events Summary
Paul Wilson is a software architect in Atlanta, currently with a medical device company. He specializes in Microsoft technologies, including .NET, C#, ASP, SQL, COM+, and VB. His WilsonWebForm Control allows Multiple Forms and Non-PostBack Forms in ASP.NET. He is a Microsoft MVP in ASP.NET and is also recognized as an ASPFriend’s ASPAce/ASPElite. He is a moderator on Microsoft’s ASP.NET Forums, as well as one of the top posters. He is certified in .NET (MCAD), as well as also holding the MCSD, MCDBA, and MCSE. Please visit his website, www.WilsonDotNet.com, or email him at Paul@WilsonDotNet.com.