Saving and loading of ASP. NET views (1) -- saving of views

Source: Internet
Author: User

ASP. NET has two important stages in the page lifecycle: loading and saving views. The following two stages are discussed in detail. Finally, ASP is discussed. A New View mechanism ConrolState introduced by NET 2.0

 

Before reading this article, you must understand that the Page class of the asp.net Page itself is a control. Therefore, the control mentioned in this Article refers to both the Page itself and the various controls on the Page, in addition, this article discusses asp.net's two sets of view mechanisms. One is the ViewState that everyone is familiar, another mechanism is the ConrolState added by asp.net 2.0, which is represented in the text by the control state.

 

1. View Storage

Figure 1

 

1. The view calls a SaveAllState function during the Save process:

Code

Private void SaveAllState ()
{
If (this. _ needToPersistViewState)
{
Pair state = new Pair ();
IDictionary dictionary = null;
If (this. _ registeredControlsRequiringControlState! = Null) & (this. _ registeredControlsRequiringControlState. Count> 0 ))
{
Dictionary = new HybridDictionary (this. _ registeredControlsRequiringControlState. Count + 1 );
Foreach (Control control in (IEnumerable) this. _ registeredControlsRequiringControlState)
{
Object obj2 = control. SaveControlStateInternal ();
If (dictionary [control. UniqueID] = null) & (obj2! = Null ))
{
Dictionary. Add (control. UniqueID, obj2 );
}
}
}
If (this. _ registeredControlsThatRequirePostBack! = Null) & (this. _ registeredControlsThatRequirePostBack. Count> 0 ))
{
If (dictionary = null)
{
Dictionary = new HybridDictionary ();
}
Dictionary. Add ("_ ControlsRequirePostBackKey _", this. _ registeredControlsThatRequirePostBack );
}
If (dictionary! = Null) & (dictionary. Count> 0 ))
{
State. First = dictionary;
}
Pair pair2 = new Pair (this. GetTypeHashCode (). ToString (NumberFormatInfo. InvariantInfo), base. SaveViewStateRecursive ());
If (this. Context. TraceIsEnabled)
{
Int viewstateSize = 0;
If (pair2.Second is Pair)
{
ViewstateSize = base. EstimateStateSize (Pair) pair2.Second). First );
}
Else if (pair2.Second is Triplet)
{
ViewstateSize = base. EstimateStateSize (Triplet) pair2.Second). First );
}
This. Trace. AddControlStateSize (this. UniqueID, viewstateSize, (dictionary = null )? 0: base. EstimateStateSize (dictionary [this. UniqueID]);
}
State. Second = pair2;
This. SavePageStateToPersistenceMedium (state );
}
}

 

From this code, we can see that in LoadAllState, ASP. NET First uses a System. Web. Pair object. It has two fields, First and Second, all of which are of the object type.

IDictionary dictionary = null;
If (this. _ registeredControlsRequiringControlState! = Null) & (this. _ registeredControlsRequiringControlState. Count> 0 ))
{
Dictionary = new HybridDictionary (this. _ registeredControlsRequiringControlState. Count + 1 );
Foreach (Control control in (IEnumerable) this. _ registeredControlsRequiringControlState)
{
Object obj2 = control. SaveControlStateInternal ();
If (dictionary [control. UniqueID] = null) & (obj2! = Null ))
{
Dictionary. Add (control. UniqueID, obj2 );
}
}
}
If (this. _ registeredControlsThatRequirePostBack! = Null) & (this. _ registeredControlsThatRequirePostBack. Count> 0 ))
{
If (dictionary = null)
{
Dictionary = new HybridDictionary ();
}
Dictionary. Add ("_ ControlsRequirePostBackKey _", this. _ registeredControlsThatRequirePostBack );
}
If (dictionary! = Null) & (dictionary. Count> 0 ))
{
State. First = dictionary;
}

This code is used to read the status of all controls on the page. foreach (Control control in (IEnumerable) this. _ registeredControlsRequiringControlState)
Traverse all the widgets registered on the page that want to use the control status, and then
Object obj2 = control. SaveControlStateInternal ();
If (dictionary [control. UniqueID] = null) & (obj2! = Null ))
{
Dictionary. Add (control. UniqueID, obj2 );
}

Read the control status through SaveControlStateInternal () in sequence and save it in a hash set dictionary based on the unique ID of the control.

Continue to dive deeper. What has been done in SaveControlStateInternal?

Internal object SaveControlStateInternal ()
{
Object x = this. SaveControlState ();
Object y = null;
If (this. _ adapter! = Null)
{
Y = this. _ adapter. SaveAdapterControlState ();
}
If (x = null) & (y = null ))
{
Return null;
}
Return new Pair (x, y );
}

This function reads the control state through the SaveControlState first, but the SaveControlState is a virtual empty function, and you will find a retrun null statement in it, this shows where the value of the control status comes from when the control status is to be used (which can be discussed later). Next this. _ adapter! = Null if the control adapter is not empty, SaveControlStateInternal also uses _ adapter. the SaveAdapterControlState is used to save the control state logic from the perspective of the adapter class. If the control specifies the adapter, you must implement the read logic of the corresponding control state. Finally, according to X, returns a null or Pair value for the value of Y.

Return to SaveAllState.

Pair pair2 = new Pair (this. GetTypeHashCode (). ToString (NumberFormatInfo. InvariantInfo), base. SaveViewStateRecursive ());
If (this. Context. TraceIsEnabled)
{
Int viewstateSize = 0;
If (pair2.Second is Pair)
{
ViewstateSize = base. EstimateStateSize (Pair) pair2.Second). First );
}
Else if (pair2.Second is Triplet)
{
ViewstateSize = base. EstimateStateSize (Triplet) pair2.Second). First );
}
This. Trace. AddControlStateSize (this. UniqueID, viewstateSize, (dictionary = null )? 0: base. EstimateStateSize (dictionary [this. UniqueID]);
}
State. Second = pair2;

This Code reads the view status and calculates the size of view information. The core of this Code is base. saveViewStateRecursive (). This function recursively reads the view information of the page Control tree. See:

Internal object SaveViewStateRecursive ()
{
If (! This. flags [4])
{
Object y = null;
If (this. _ adapter! = Null)
{
Y = this. _ adapter. SaveAdapterViewState ();
}
Object x = this. SaveViewState ();
ArrayList z = null;
If (this. HasControls ())
{
ControlCollection controls = this. _ occasionalFields. Controls;
Int count = controls. Count;
Bool loadViewStateByID = this. LoadViewStateByID;
For (int I = 0; I <count; I ++)
{
Control control = controls [I];
Object obj4 = control. SaveViewStateRecursive ();
If (obj4! = Null)
{
If (z = null)
{
Z = new ArrayList (count );
}
If (loadViewStateByID)
{
Control. EnsureID ();
Z. Add (control. ID );
}
Else
{
Z. Add (I );
}
Z. Add (obj4 );
}
}
}
If (this. _ adapter! = Null)
{
If (x! = Null) | (y! = Null) | (z! = Null ))
{
Return new Triplet (x, y, z );
}
}
Else if (x! = Null) | (z! = Null ))
{
Return new Pair (x, z );
}
}
Return null;
}
This function first uses this if the control adapter is not empty. _ adapter. saveAdapterViewState () reads view information from the adapter's perspective, and then this. the SaveViewState () is read from the View information of the control itself:

Protected virtual object SaveViewState ()
{
If (this. flags [0x20])
{
This. ViewState ["Visible"] =! This. flags [0x10];
}
If (this. _ viewState! = Null)
{
Return this. _ viewState. SaveViewState ();
}
Return null;
}

This. _ viewState is the ViewState set we usually use. When SaveViewState () is used for it, every value of ViewState is encapsulated into an ArrayList and returned.

Return to SaveViewStateRecursive

ArrayList z = null;
If (this. HasControls ())
{
ControlCollection controls = this. _ occasionalFields. Controls;
Int count = controls. Count;
Bool loadViewStateByID = this. LoadViewStateByID;
For (int I = 0; I <count; I ++)
{
Control control = controls [I];
Object obj4 = control. SaveViewStateRecursive ();
If (obj4! = Null)
{
If (z = null)
{
Z = new ArrayList (count );
}
If (loadViewStateByID)
{
Control. EnsureID ();
Z. Add (control. ID );
}
Else
{
Z. Add (I );
}
Z. Add (obj4 );
}
}
}

This is an important part of SaveViewStateRecursive, that is, recursively reading the child control's view. HasControls can determine whether the control contains child controls. If it is not natural, no recursion is required. ControlCollection controls = this. _ occasionalFields. controls; the Child control set of the control is returned, and the Child control recursively calls object obj4 = control. saveViewStateRecursive () returns the child control view as obj4, and then places the child control view into an array list z, it must be noted that the views and controls of the controls in the array list are a pair of existing controls, which indicate that the control value can be the control ID or the control index in the control tree:

If (loadViewStateByID)
{
Control. EnsureID ();
Z. Add (control. ID );
}
Else
{
Z. Add (I );
}
Z. Add (obj4 );

As shown above, first put the Control ID or index into z, and then put the control view into z

Finally:
If (this. _ adapter! = Null)
{
If (x! = Null) | (y! = Null) | (z! = Null ))
{
Return new Triplet (x, y, z );
}
}
Else if (x! = Null) | (z! = Null ))
{
Return new Pair (x, z );
}
If the control adapter, the control itself, and the control's sub-control obtain the view value, the view of the three elements will be encapsulated into a Triplet object (like Pair, there are only three object members ), if the view of the adapter is not obtained, the view of the control itself and the view of the sub-control are encapsulated into a Pair return. No matter which form the view is returned, we need to have this concept in mind, the returned view information is a tree structure that is recursively determined based on the control tree.

 

Return to SaveAllState

Finally, the control status and view are encapsulated into a Pair object state.

State. First = dictionary;
//..........

State. Second = pair2;
This. SavePageStateToPersistenceMedium (state );

 

Call SavePageStateToPersistenceMedium (state)

Protected internal virtual void SavePageStateToPersistenceMedium (object state)
{
PageStatePersister pageStatePersister = this. PageStatePersister;
If (state is Pair)
{
Pair pair = (Pair) state;
PageStatePersister. ControlState = pair. First;
PageStatePersister. ViewState = pair. Second;
}
Else
{
PageStatePersister. ViewState = state;
}
PageStatePersister. Save ();
}

SavePageStateToPersistenceMedium retrieves the state control status and view to construct a PageStatePersister object. This object has two important attributes: ControlState and ViewState.

PageStatePersister. ControlState = pair. First;
PageStatePersister. ViewState = pair. Second;

 

Finally, the pageStatePersister. Save () is serialized and the serialized information is saved as the input on the webpage on the client. The whole view saving process is completed.
The serialization information stored on the page is familiar to you:

<Input type = "hidden" name = "_ VIEWSTATE" id = "_ VIEWSTATE" value = "/wEPDwUJNzYwOTI5OTA4ZGQrXkI1DTujGF3xmo0Bgq2iNeJ0vQ ="/>
Therefore, you must be confused by name = "_ VIEWSTATE" id = "_ VIEWSTATE". This input contains not only the ViewState value but also the ControlState value.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.