1. Basic introduction to server scripts
First, let’s review the basic execution methods of Web server pages:
1. The client sends a request to the server by typing the address in the address bar of the browser
2. After the server receives the request, it sends it to The corresponding server-side page (that is, a script) is executed. The script generates a response from the client and sends it back to the client.
3. The client browser receives the response from the server, parses the Html, and presents the graphical web page to the user. For
the interaction between the server and the client, the following main methods are usually used:
1. Form: This is the most important method. Standardized controls are used to obtain user input. The submission of the Form sends the data to the server for processing.
2. QueryString: By adding parameters after the Url, the parameters are transmitted to the server. This method is actually the same as the Get method.
3. Cookies: This is a special method, usually used to confirm the user's identity
. 2. ASP.Net Introduction
Traditional server script languages, such as ASP, JSP, etc., write server scripts in much the same way. They all embed interpreted or compiled and executed codes in Html, and the server platform executes these codes to generate Html; for similar scripts, pages The life cycle of Servlet is actually very simple, that is, all the code is executed from the beginning to the end. Of course, Servlet written in Java can write more complex code, but from a structural point of view, it is no different from JSP.
The emergence of ASP.Net broke this tradition; ASP.Net adopted CodeBehind technology and server-side controls, added the concept of server-side events, changed the scripting language writing model, and became closer to Window programming, making Web programming easier. , intuitive; but we have to see that ASP.Net itself does not change the basic model of Web programming, it just encapsulates some details and provides some easy-to-use functions, making the code easier to write and maintain; to a certain extent , complicating the way of server-side execution. This is the main topic we are going to discuss today: the life cycle of ASP.Net Web Page.
3. ASP.Net request processing mode
We say that ASP.Net's Web Page does not break away from the Web programming mode, so it still works in the mode of request->receive request->process request->send response. Each interaction with the client will trigger a new request, so the life cycle of a Web Page is based on one request.
When IIS receives a request from the client, it will hand the request to the aspnet_wp process for processing. This process will check whether the requested application domain exists. If it does not exist, it will create one, and then create an Http runtime (HttpRuntime ) to handle requests, this runtime "provides a set of ASP.NET runtime services for the current application" (from MSDN).
When HttpRuntime processes requests, it will maintain a series of application instances, that is, instances of the application's Global class (global.asax). These instances will be stored in an application pool when there are no requests (actually The application pool is maintained by another class, HttpRuntime is just a simple call). Every time a request is received, HttpRuntime will obtain an idle instance to process the request. This instance will not process other requests before the request ends. After the processing is completed , it will go back to the pool, "An instance is used to handle multiple requests during its lifetime, but it can only handle one request at a time." (Excerpted from MSDN)
When the application instance handles the request, it will Create an instance of the request page class and execute its ProcessRequest method to process the request. This method is the beginning of the Web Page life cycle.
4. Aspx page and CodeBehind
Before we delve into the life cycle of the page, let's first discuss some of the relationships between Aspx and CodeBehind.
<%@ Page language="c#" Codebehind="WebForm.aspx.cs" Inherits="MyNamespace.WebForm" %>
I believe that friends who have used CodeBehind technology should be very familiar with this sentence at the top of ASPX. Let's Analyze it one by one:
Page language="c#" Needless to say,
Codebehind="WebForm.aspx.cs" This sentence indicates the bound code file
Inherits="MyNamespace.WebForm" This sentence is very important. It represents the class name inherited by the page, which is the class in the code file of CodeBehind. This class must be derived from System.Web.WebControls.Page.
From the above we can analyze that in fact, the class in CodeBehind is the basis of the page (ASPX). Classes, at this point, some friends may want to ask. When writing ASPX, you embed code or server controls in Html exactly according to the ASP method. Do you not see the shadow of the so-called "classes"?
This problem is actually not complicated. Friends who use ASP.Net programming can go to your system disk: WINDOWSMicrosoft.NETFramework<version number>Temporary ASP.NET Files, and put it below All temporary files of ASP.Net applications that exist on this machine. The name of the subdirectory is the name of the application, and then go down two levels (in order to ensure uniqueness, ASP.Net automatically generates two levels of subdirectories, and the subdirectory The name is random), and then we will find that there are many link libraries similar to: "yfy1gjhc.dll", "xeunj5u3.dll" and sources such as "komee-bp.0.cs" and "9falckav.0.cs" file, in fact, this is the result of ASPX being dynamically compiled by ASP.Net. When we open these source files, we can find:
public class WebForm_aspx: MyNamespace.WebForm, System.Web.SessionState.IRequiresSessionState.
This confirms our previous statement, ASPX It is a subclass of the code binding class. Its name is the ASPX file name plus the "_aspx" suffix. By studying these codes, we can find that in fact all server controls defined in aspx are generated in these codes, and then When these codes are dynamically generated, the code originally embedded in ASPX is written in the corresponding location.
When a page is visited for the first time, the HTTP runtime will use a code generator to parse the ASPX file and generate source code and compile it. Then subsequent visits will directly call the compiled dll. This is why ASPX The reason why the access is very slow.
Having explained this problem, let’s look at another problem. When we use code binding, drag a control on the design page, and then switch to the code view, you can use the control directly in Page_Load. Since the control is generated in the subclass, why can it be used in the parent class? What about using it directly?
In fact, we can find that whenever we use VS.Net to drag a control onto the page, a statement similar to this is always added to the code binding file:
protected System.Web.WebControls.Button Button1;
We can find that this field is Declare it as protected, and the name is consistent with the ID of the control in ASPX. If you think about it carefully, this problem will be solved. We mentioned earlier that the source code of ASPX is dynamically generated and compiled by the generator. The generator will generate the code to dynamically generate each server control. When generating, it will check whether the parent class has declared this control. If so, , it will add a code similar to the following:
this.DataGrid1 = __ctrl;
This __ctrl is the variable that generates the control. At this time, it assigns the reference of the control to the corresponding variable in the parent class, which is why in the parent class The declaration must be protected (actually it can also be public), because it is necessary to ensure that subclasses can call it.
Then when Page_Load is executed, because the declaration of the parent class has been assigned a value by the initialization code in the subclass, we can use this field to access the corresponding control. Knowing this, we will not commit code binding. Using the control in the constructor in the specified file causes a null reference exception error. Because the constructor is executed first, the initialization of the subclass has not yet started, so the fields in the parent class have null values. As for the subclass We will discuss later when a class is initialized.
5. Page Life Cycle
Now back to the content mentioned in the third title, we talked about the instance of HttpApplication receiving the request and creating an instance of the page class. In fact, this instance is an instance of the dynamically compiled ASPX class. In the previous title we learned that ASPX is actually a subclass of the class in the code binding, so it inherits all protected methods.
Now let's take a look at the code of the CodeBehind class automatically generated by VS.Net to start our discussion of the page life cycle:
#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Forms designer.
//
InitializeComponent();
base.OnInit(e);
}
/// <summary>
/// Designer supports required methods - do not use code editor to modify
/// The content of this method.
/// </summary>
private void InitializeComponent()
{
this.DataGrid1.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.DataGrid1_ItemDataBound);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
This is the code for Page generated using VS.Net. Let's take a look. There are two methods in it, one is OnInit and the other is InitializeComponent. The latter is called by the former. In fact, this is the beginning of page initialization. In InitializeComponent we see the event declaration of the control and the Load declaration of the Page.
The following is a description excerpted from MSDN and a sequence table of page life cycle methods and event triggering:
"Each time an ASP.NET page is requested, the server loads an ASP.NET page and unloads the page when the request is completed. The page and the server controls it contains are responsible for executing the request and rendering the HTML to the client. Although the communication between the client and the server is stateless and intermittent, it must be perceived by the client as a continuous process. ."
"This illusion of continuity is implemented by the ASP.NET page framework, the page, and its controls. After a postback, the behavior of the control must appear to start from where the last Web request ended. Frameworks can make execution state management relatively easy, but in order to achieve continuity effects, control developers must know the execution order of controls. Control developers need to understand what information can be used and what data can be retained by the control at each stage of the control life cycle. , the state in which a control is rendered. For example, a control cannot call its parent until the control tree on the page is populated." The following table provides a high-level overview of the stages in the control lifecycle. Click in the table. link."
stage | control needs to perform an action | to override the initialization method or event |
initialize | the settings required within the life cycle of an incoming Web request. See Handling Inherited Events. | Init event (OnInit method) |
loads the view state. | At the end of this phase, the ViewState property of the control will be automatically populated. For details, see the introduction in Maintaining the State in the Control. A control can override the default implementation of the LoadViewState method to restore it to a custom state. | The LoadViewState method |
handles the postback data | , processes the incoming form data, and updates the properties accordingly. See Handling Postback Data. Note Only controls that handle postback data participate in this phase. | The LoadPostData method (if IPostBackDataHandler is implemented) |
loads and | performs operations common to all requests, such as setting up a database query. At this point, the server controls in the tree have been created and initialized, the state has been restored, and the form controls reflect the client's data. See Handling Inherited Events. | Load event (OnLoad method) |
Send postback change notifications | Raise a change event in response to a state change between the current and previous postbacks. See Handling Postback Data. Note Only controls that raise postback change events participate in this phase. | The RaisePostDataChangedEvent method (if IPostBackDataHandler is implemented) |
handles postback events. | It handles client events that cause postbacks and raises the appropriate events on the server. See Capturing Postback Events. Note Only controls that handle postback events participate in this phase. | The RaisePostBackEvent method (if IPostBackEventHandler is implemented) |
prerenders | perform any updates before rendering the output. Changes to a control's state during the prerendering phase can be saved, while changes made during the rendering phase are lost. See Handling Inherited Events. | The PreRender event (OnPreRender method) |
saves state | after this phase, automatically persisting the control's ViewState property into a string object. This string object is sent to the client and back as a hidden variable. To improve efficiency, controls can override the SaveViewState method to modify the ViewState property. See Maintaining state in controls. | The SaveViewState method |
renders | the output that is presented to the client. See Rendering ASP.NET Server Controls. | The Render method |
handles | all final cleanup operations before destroying the control. References to expensive resources, such as database links, must be released at this stage. See methods in ASP.NET server controls. | The Dispose method |
offloads | all final cleanup operations before destroying the control. Control authors typically perform cleanup in Dispose without handling this event. | UnLoad event (On UnLoad method) |
From this table, we can clearly see the methods called and the triggering time of a Page from loading to unloading. Next, we will analyze it in depth.
After looking at the above table, attentive friends may ask, since OnInit is the beginning of the page life cycle, and we talked about controls being created in subclasses in the previous lecture, here we actually use the InitializeComponent method Fields declared in the parent class can already be used, so does it mean that the subclass is initialized before this?
In the third title, we mentioned that the ProcessRequest of the page class is the beginning of the page declaration cycle in the true sense. This method is called by HttpApplication (the calling method is more complicated, and I will have the opportunity to write a separate article to explain it). A Page The processing of the request starts from this method. By decompiling the .Net class library to view the source code, we found the base class of System.Web.WebControls.Page: System.Web.WebControls.TemplateControl (it is the page and user control A "FrameworkInitialize" virtual method is defined in the base class), and then this method is first called in the ProcessRequest of the Page. We found traces of this method in the ASPX source code generated by the generator. All controls are in It is initialized in this method, and the control tree of the page is generated at this time.
The next thing is simple, let's gradually analyze each item of the page life cycle:
1. Initialization
Initialization corresponds to the Init event and OnInit method of the Page.
If you want to rewrite, MSDN recommends overloading the OnInti method instead of adding a proxy for the Init event. There is a difference between the two. The former can control the order in which the OnInit method of the parent class is called, while the latter can only be used in the parent class. Executed after OnInit (actually called in OnInit).
2. Loading view state
This is a more important method. We know that each request is actually processed by a different page class instance. In order to ensure the state between two requests, ASP.Net uses ViewState.
The LoadViewState method obtains the last state from ViewState, and uses recursion to traverse the entire tree according to the structure of the control tree on the page to restore the corresponding state to each control.
3. Processing postback data
This method is used to check whether the status of the control data sent back by the client has changed. Prototype of the method:
public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)
postDataKey is the keyword that identifies the control (that is, the Key in postCollection). postCollection is a collection containing postback data. We can override this method and then check the return Whether the data sent has changed, if so, it returns a True, "LoadPostData returns true if the control state changes due to postback; otherwise it returns false. The page framework tracks all controls that return true and calls RaisePostDataChangedEvent on these controls. "(Excerpted from MSDN)
This method is defined in System.Web.WebControls.Control, and is also the method that all custom controls that need to handle events need to handle. For the Page we are discussing today, you can leave it alone.
4. Loading
corresponds to the Load event and OnLoad method. I believe most friends will be familiar with this event. The Page_Load method in the page generated by VS.Net is the method to respond to the Load event. For every request, the Load event will be triggered. , the Page_Load method will also be executed. I believe this is also the first step for most people to understand ASP.Net.
The Page_Load method responds to the Load event, which is defined in the System.Web.WebControl.Control class (this class is the ancestor of Page and all server controls) and is triggered in the OnLoad method.
Many people may have encountered such a thing. They wrote a PageBase class and then verified the user information in Page_Load. It turned out that no matter whether the verification was successful or not, the Page_Load of the subclass page will always be executed first. At this time, some information may be left. As a security risk, the user may execute the Page_Load method in the subclass without being authenticated.
The reason for this problem is very simple, because the Page_Load method is added to the Load event in OnInit, and the OnInit method of the subclass first adds the Load event and then calls base.OnInit, which causes the subclass The Page_Load is added first, then executed first.
It is also very simple to solve this problem. There are two methods:
1) Overload the OnLoad method in PageBase, then authenticate the user in OnLoad, and then call base.OnLoad, because the Load event is triggered in OnLoad, so we can ensure Authenticate the user before firing the Load event.
2) First call base.OnInit in the OnInit method of the subclass to ensure that the parent class executes Page_Load first.
5. Send postback change notification.
This method corresponds to the processing of postback data in step 3. If the postback data is processed, True is returned. The page framework will call this method to trigger data change events, so the postback data change event of the custom control needs to be triggered in this method.
Similarly, this method is not very useful for Page. Of course, you can also define data change events on the basis of Page. This is of course also possible.
6. Handle postback events
This method is where most server control events are triggered. When the request contains information about control event triggers (events of server controls are another topic, I will write another article to discuss in the near future), the page control The RaisePostBackEvent method of the corresponding control will be called to trigger the server-side event.
Here comes another common question:
Netizens often ask why the submitted data has not changed after modification.
In most cases, they do not understand the triggering process of server events. We can see that the server event is triggered after the Load of the Page. , that is to say, the page will first execute Page_Load, and then execute the click event of the button (here is the button as an example). Many friends bind data in Page_Load, and then process the changes in the button event. There is a problem with this. , Page_Load is always executed before the button event, which means that before the data has time to change, the data binding code in Page_Load is executed first, and the original data is assigned to the control, then when the button event is executed, What is actually obtained is the original data, so the update will of course have no effect.
It is also very simple to change this problem. A more reasonable approach is to write the data binding code into a method, let's assume it is BindData:
private void BindData()
{
//Bind data
}
Then modify PageLoad:
private void Page_Load( object sender,EventArgs e)
{
if(!IsPostBack)
{
BindData(); //Bind data when the page is accessed for the first time}
}
Finally in the button event:
private Button1_Click( object sender,EventArgs e )
{
//Update dataBindData();//Rebind data
}
7.
The processing of the final request for pre-rendering will be converted into a response sent back to the server. The pre-rendering stage is to perform the state changes made before the final rendering, because before rendering a control, we must generate Html based on its properties. , such as the Style attribute, which is the most typical example. Before pre-rendering, we can change the Style of a control. When pre-rendering is performed, we can save the Style and display Html style information as the rendering stage.
8. Save the state.
This stage is for the loading state. We have mentioned many times that different instances are processing between requests, so we need to save the state of this page and control. This stage is to write the state. ViewState stage.
9. At
this point, the page's request processing has basically come to an end. In the Render method, the control tree of the entire page will be recursed, the Render method will be called in sequence, and the corresponding Html code will be written into the final response stream.
10. Disposal
is actually the Dispose method. At this stage, occupied resources, such as database connections, will be released.
11.
At the end of unloading, the page will execute the OnUnLoad method to trigger the UnLoad event, which handles the final processing before the page object is destroyed. In fact, ASP.Net provides this event only for design considerations. Usually the release of resources is completed in the Dispose method. So this method has become useless.
We briefly introduced the life cycle of the page, and gave a less in-depth explanation of the processing of server-side events. Today I mainly want everyone to understand the cycle of page execution. I will write some more about the events and lifetime of server controls in the future. article to discuss.
These contents are some of my experiences on Page research when I was learning ASP.Net. The specific details are not discussed in detail. Please refer to MSDN for more information, but I have cited some common mistakes and mistakes made by beginners. The reasons, I hope it can bring inspiration to everyone.