Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

A Dive into ASP.NET Page Life Cycle

0.00/5 (No votes)
26 Nov 2014 1  
ASP.NET page/master page/user control's life cycle from the perspective of Session and View State

Introduction

After reading this article, you will be able to answer questions like:

  • What is the sequence of Page Events?
  • What are events and what are methods in Page Life Cycle?
  • What is the page event on which you can access view state? OR What is the page event on which you can access property of control?
  • If I have a Page which has a master page and a user control, what will be the sequence of Load, init, etc.?
  • On which event can you add controls, master page, theme to the page earliest?

What is the practical need to know sequences of event in ASP.NET Page life cycle?

Consider a scenario where you have a Page named Home.aspx, with user control named Control.ascx, and a Master Page. You are modifying something in the session, on all these three but in certain order like adding product ID to session from the page when user picks some listed product, checking on the Master page if the user has permission to view a particular product on that page, and opening the detail of product in the user control. To perform these kind of operations, it is essential for you to know the sequence of execution.

Let us do a quick experiment and let these three (Page, master, user control) tell the sequence.

You will create a web page, with a user control and master page. In three of these, you will describe the page events like Page_Load, Page_PreInit, etc., where the name of corresponding event will be stored inside a session variable and later the value inside session variable will be written off to the page.

Using the Code

  1. Create an empty ASP.NET web project.
  2. Add two master pages Old.master, New.master. Add a label inside New.master with ID "lblMaster".
  3. Add a page named Home.aspx assign it Old.master. Put a panel inside it with ID "pnlMain". Drop a label on Page named "lblHead".
  4. Add an user Control named "Control.aspx". Put a label inside it which identifies the control on the page, for example : "Hi from User Control !".
  5. Add a skin file named "MyTheme". Do a simple styling of Label control there by adding the following line of code:
    <asp:Label runat="server"  BackColor="White" ForeColor="Blue">
    </asp:Label>

Following are the page events we are going to encounter:

  1. Page_PreInit
  2. Page_Init
  3. Page_InitComplete
  4. Page_PreLoad
  5. Page_Load
  6. Page_LoadComplete
  7. Page_PreRender
  8. Page_PreRenderComplete
  9. Page_SaveStateComplete
  10. Render
  11. Unload

Among these, Render is a method which gets executed for each control, and also for page.

The unload method comes already implemented in the complementer page class, which we can override.

Session is something that is accessible to all of these events starting from "PreInIt" to "OnUnload". But "SaveStateComplete" is the last event which can modify the "Response". Following lines of code store the event names inside session and write the session value to response, paste the code inside the code behind file:

protected void Page_Load(object sender, EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/>  Page_Load";
            ViewState["E"] = Convert.ToString(ViewState["E"]) + 
            "<br/> Page_Load";
        }

        protected void Page_PreInit(object sender, EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/>  Page_PreInit";
            if (!IsPostBack)//IsPostBack property can be checked in Page_PreInit event.
            {
                Page.MasterPageFile = "New.Master";//Master Page can be assigned 
                            //dynamically in Page_PreInit event.
                Label lblMas = (Label)Page.Master.FindControl("lblMaster");
                lblMas.Text = "<br/> I am the master page , 
                I was set from Page_PreInit event dynamically, 
                I am blue because of dynamic theme applied to me";
                Label lblNew = new Label();
                lblNew.Text = "<br/> I am the control added Dynamically in Page_PreInit, 
                I am blue because of dynamic skin applied to me, 
                these properties can be overridden in further page events.";
                pnlMain.Controls.Add(lblNew);//Controls can be added dynamically in Page_PreInit event.
                Page.Theme = "MyTheme";// Theme can be applied dynamically in Page_PreInit
                ViewState["E"] = Convert.ToString
                (ViewState["E"]) + "<br/>   Page_PreInit";
            }
            else
            {
                //lblHead.Text = "This will give an exception if running, 
                //as control cannot be created from the view state at this event.";
                if (Convert.ToString(ViewState["E"]) == string.Empty)
                    ViewState["E2"] = "<br/> <br/> 
                    Page Posted Back <br/>  Nothing here in view State Page_PreInit";
                else
                    ViewState["E2"] = Convert.ToString(ViewState["E"]) + 
                    "<br/> <b> View State found in Page_PreInit</b>";
            }
        }

        protected void Page_Init(object sender, EventArgs e)
        {
            //lblHead.Text = "This will give an exception when running, 
            //as control cannot be created from the view state at this event.";
            if (!IsPostBack)
            {
                Session["E"] = Convert.ToString(Session["E"]) + 
                "<br/>  Page_Init";
                Label lblNew = new Label();
                lblNew.Text = "<br/> 
                I am the control added Dynamically from preinit.";
                pnlMain.Controls.Add(lblNew);
                ViewState["E"] = 
                Convert.ToString(ViewState["E"]) + "<br/>    Page_Init";
            }
            else
            {
                if (Convert.ToString(ViewState["E"]) == string.Empty)
                    ViewState["E2"] = Convert.ToString(ViewState["E2"]) + 
                    "<br/>" + "<br/>  Nothing here in view State Page_Init";
                else
                    ViewState["E2"] = Convert.ToString(ViewState["E2"]) + 
                    Convert.ToString(ViewState["E"]) + "<br/> 
                    <b> View State found in Page_Init</b>";                
            }
        }

        protected void Page_InitComplete(object sender, EventArgs e)
        {
            //lblHead.Text = "This will give an exception if running, 
            //as control cannot be created from the view state at this event.";
            if (!IsPostBack)
            {
                Session["E"] = 
                Convert.ToString(Session["E"]) + "<br/>  Page_InitComplete";
                Label lblNew = new Label();
                lblNew.Text = "<br/> 
                I am the control added Dynamically from init complete.";
                pnlMain.Controls.Add(lblNew);
                ViewState["E"] = Convert.ToString(ViewState["E"]) + 
                "<br/>     Page_InitComplete";
            }
            else
            {
                if (Convert.ToString(ViewState["E"]) == string.Empty)
                    ViewState["E2"] = Convert.ToString(ViewState["E2"]) + 
                    "<br/>" + "<br/>  
                    Nothing here in view State Page_InitComplete";
                else
                    ViewState["E2"] = Convert.ToString(ViewState["E2"]) + 
                    Convert.ToString(ViewState["E"]) + "<br/> <b> 
                    View State found in Page_InitComplete</b>";
            }
        }
        //End InitComplete
        protected void Page_PreLoad(object sender, EventArgs e)
        {
            //lblHead.Text = "This will not give an exception when running, 
            //as control can be created from the view state at this event.";
            if (!IsPostBack)
            {
                Session["E"] = Convert.ToString(Session["E"]) + 
                "<br/>  Page_PreLoad";
                ViewState["E"] = Convert.ToString(ViewState["E"]) + 
                "<br/>   Page_PreLoad";
            }
            else
            {
                if (Convert.ToString(ViewState["E"]) == string.Empty)
                    ViewState["E2"] = Convert.ToString(ViewState["E2"]) + 
                    "<br/>" + "<br/>  
                    Nothing here in view State Page_PreLoad";
                else
                    ViewState["E2"] = Convert.ToString(ViewState["E2"]) + 
                    Convert.ToString(ViewState["E"]) + "<br/> 
                    <b> View State found in Page_PreLoad</b>";
            }
        }
        //End PreLoad
 
        protected void Page_LoadComplete(object sender, EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/>  Page_LoadComplete";
            ViewState["E"] = Convert.ToString(ViewState["E"]) + 
            "<br/>   Page_LoadComplete";
        }
        //End LoadComplete
        protected void Page_PreRender(object sender, EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/>  Page_PreRender";
            ViewState["E"] = Convert.ToString(ViewState["E"]) + 
            "<br/>   Page_PreRender";
        }
        //End PreRender
        protected void Page_PreRenderComplete(object sender, EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/>  Page_PreRenderComplete";
            ViewState["E"] = Convert.ToString(ViewState["E"]) + 
            "<br/>   Page_PreRenderComplete";
        }
        //End PreRenderComplete
        protected void Page_SaveStateComplete
        (object sender, EventArgs e)//This is the last event in page life cycle
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/>  Page_SaveStateComplete";
            ViewState["E"] = Convert.ToString(ViewState["E"]) + 
            "<br/>   Page_SaveStateComplete";
            Response.Write("<br/><br/><br/><b>Session State</b>" + 
            Convert.ToString(Session["E"])+"<br/><b>Session State</b>");
            Response.Write("<br/><b>View State</b>" + 
            Convert.ToString(ViewState["E"]));
            Response.Write("<br/><b>View State</b>" + 
            Convert.ToString(ViewState["E2"]));
        }
        //End SaveStateComplete


        protected void btnPostBack_Click(object sender, EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/>  Control Event";
        }

        protected override void OnUnload( EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/> Page Unload";
        }

This page also contains some of the lines for further experiment with Post Back, just go through the code and run the page, you will see all the page events stored in session and ViewState in the following sequence:

  1. Page_PreInit
  2. Page_Init
  3. Page_InitComplete
  4. Page_PreLoad
  5. Page_Load
  6. Page_LoadComplete
  7. Page_PreRender
  8. Page_PreRenderComplete
  9. Page_SaveStateComplete

Also user control and master page will be there with skin applied, the label we have put there will show the following text (in blue):

I am the master page, I was set from Page_PreInit event dynamically, I am blue because of dynamic theme applied to me.

Hi from User Control !

I am the control added Dynamically in Page_PreInit, I am blue because of dynamic skin applied to me, these properties can be overridden in further page events.
I am the control added Dynamically from preinit.
I am the control added Dynamically from init complete.

Render and Unload will execute after these events, so even if the value we set in session during unload is there, it will only appear in the next post back as "Response" object is out of context in "OnUnload".

Based on the output, you can deduce the following:

A. Master page and Theme, web control can be added dynamically on Page_PreInit, earliest.

Drop the User Control to the page.

Go to user control's code behind and store each event name inside the session by adding the following lines of code:

 protected void Page_Load(object sender, EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/> User Control Page_Load";
        }

        protected void Page_PreInit(object sender, EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/> User Control Page_PreInit";
        }
        //End PreInit
        protected void Page_Init(object sender, EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/> User Control Page_Init";
        }
        //End Init
        protected void Page_InitComplete(object sender, EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/> User Control Page_InitComplete";
        }
        //End InitComplete
        protected void Page_PreLoad(object sender, EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/> User Control Page_PreLoad";
        }
        //End PreLoad
        protected void Page_LoadComplete(object sender, EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/> User Control Page_LoadComplete";
        }
        //End LoadComplete
        protected void Page_PreRender(object sender, EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/> User Control Page_PreRender";
        }
        //End PreRender
        protected void Page_PreRenderComplete(object sender, EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/> User Control Page_PreRenderComplete";
        }
        //End PreRenderComplete
        protected void Page_SaveStateComplete(object sender, EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/> User Control Page_SaveStateComplete";
        }

        protected override void OnUnload( EventArgs e)
        {
            Session["E"] = Convert.ToString(Session["E"]) + 
            "<br/> User Control Unload";
        }

Go to new master and add the same code in its code behind there, just change the prefixes of values stored in session to 'Master Page' instead of 'User control'.

Now run the page, you will see the following output:

  1. Page_PreInit
  2. User Control Page_Init
  3. Master Page Page_Init
  4. Page_Init
  5. Page_InitComplete
  6. Page_PreLoad
  7. Page_Load
  8. Master Page Page_Load
  9. User Control Page_Load
  10. Page_LoadComplete
  11. Page_PreRender
  12. Master Page Page_PreRender
  13. User Control Page_PreRender
  14. Page_PreRenderComplete
  15. Page_SaveStateComplete

You can see that:

B. Page_Load, pre_Render event sequence of Home Page, Master Page, User Control are opposite of Page_Init event.

C. Preinit, Initcomplete, loadComplete, prerenderComplete, saveStateComplete are called once only from the Page, not from the User Control or Master page.

Now add a Button web user control to the Page, handle its click event by adding the following one line of code:

Session["E"] = Convert.ToString(Session["E"]) + 
"<br/>  Control Event";

Click the button and following is the successive output:

User Control Unload
Master Page Unload
Page Unload

Page Posted Back
Nothing here in view State Page_PreInit
Nothing here in view State Page_Init
Nothing here in view State Page_InitComplete
Page_PreInit
Page_Init
Page_InitComplete
Page_PreLoad
Page_Load
Page_LoadComplete
Page_PreRender
Page_PreRenderComplete
View State found in Page_PreLoad

You will find out:

D. Pre_Load is the first event where you will get the ViewState restored.

Clicking the button also writes the lines stored during Unload event of previous request because:

E. "Response" object is out of context in unload.

This code is also attached with the code name Delta.

Points of Interest

By debugging these code snippets and bringing some other incident like DataBinding, databaseConnection, Configuration Access, Application State in the scene, you can find out more interesting results.

History

  • 26th November, 2014: Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here