State Management, IStateManager , and the ViewState


State Management, IStateManager , and the ViewState Dictionary

We'll now take a closer look at view state management, starting where we left off in Chapter 7. View state is the ASP.NET state management mechanism that the page framework uses to serialize the state that needs to be restored after each round-trip to the client. In this section, we'll examine how the page serializes and restores its view state, how custom types can participate in state management, and how the ViewState property performs default state management for a control.

How a Page Serializes and Restores Its View State

We described a control's life cycle in Chapter 9. In the Save View State phase, a page recursively invokes the SaveViewState method on each control in its control tree. In turn , each control returns an object that contains the information it needs to restore its state on a postback request. The page then creates an object graph that represents its own state information, which includes the objects returned by its child controls as well as other objects that contain information about the control tree. This object graph constitutes the view state of the page. In its Render phase, the page serializes its view state to a string representation by utilizing an instance of the System.Web.UI . LosFormatter class, a utility class that performs serialization that is optimized for a number of commonly used types. The serialized view state string is round-tripped to the client in the __VIEWSTATE hidden field by default, as we showed in Chapter 7.

In its LoadViewState method, a page creates a LosFormatter object to deserialize the string representation of the view state back into an object graph. The page then performs the inverse of the operations it performed in SaveViewState . It recursively invokes the LoadViewState method of each child control by handing to it the object that represents the saved state for that control. Each control must perform logic to restore its own state in its LoadViewState method.

The LosFormatter class is optimized to perform serialization of integers, Booleans, and strings as well as for Array , ArrayList, and Hashtable objects that contain these types. In addition, this class can serialize other primitive types, any other types that have associated type converters, and Array , ArrayList , and Hashtable objects that contain those types. LosFormatter uses type converters to convert values to and from strings. LosFormatter can also serialize types that are marked with the Serializable attribute or that implement the ISerializable interface by using binary serialization. However, serialization for those types is much slower than serialization for types that have type converters defined.

Finally, LosFormatter can optimally serialize two utility classes: Pair and Triplet . These classes are used by controls to group objects to add to the view state, as we will show later in this chapter. Any objects that your control saves in its ViewState dictionary or returns from its SaveViewState method must belong to the set of types that is serializable by the LosFormatter class. If your control saves state by using types that are not serializable by LosFormatter , your control might compile, but it will cause a run-time exception. In addition, you need to choose types that can be serialized in an optimal fashion to improve the performance of your control and of the pages in which it is used.

The default implementation of the Control class delegates state management to its ViewState dictionary. However, when your control defines complex properties, it is generally not possible to use the ViewState dictionary to manage the state of those properties. Custom types that represent complex properties can participate in state management by implementing the IStateManager interface, which we will examine next .

The IStateManager Interface

The page framework provides the System.Web.UI . IStateManager interface to allow types other than controls to participate in the view state management. This interface is defined as follows :

 publicinterfaceIStateManager{ boolIsTrackingViewState{get;} voidLoadViewState(objectstate); objectSaveViewState(); voidTrackViewState(); } 

The Control class performs state management by using the same members that are in the IStateManager contract, although Control does not implement IStateManager .

The TrackViewState method marks the end of the initialization phase, after which any modifications to properties must be tracked by the IStateManager implementation. The IsTrackingViewState property indicates that property-change tracking has started. The SaveViewState method returns an object that represents the combined state of all the properties that were modified after initialization. The LoadViewState method restores properties by using the object that was returned by SaveViewState . We'll make this discussion concrete in the next section, where we implement the IStateManager interface in a custom type.

We'll now look at the ViewState property that provides the default mechanism for state management in the Control class.

The ViewState Property and Default State Management

The ViewState property is a complex property that performs its own state management. To use the ViewState property as the storage mechanism for other properties in your control, you do not need to understand custom state management. However, we'll examine the ViewState property because it provides insight into the default state management mechanism of the Control class and enables you to mimic this mechanism when you implement state management in a custom type. In the next section, we'll define a HotSpot custom type that defines its own ViewState property to provide state management.

The type of the ViewState property is the System.Web.UI.StateBag class, which is a dictionary that participates in state management by implementing the IStateManager interface. The StateBag holds key/value pairs in which the keys are strings and the values are objects. When an object is added to a StateBag instance, StateBag automatically stores an additional bit with the object, which it uses to flag modifications to the stored object. More accurately, each item in a StateBag is a StateItem object that holds the actual property value and an associated Boolean flag that indicates whether the property is dirty , or modified after initialization.

The StateBag class implements the IStateManager interface as follows:

  • In its TrackViewState method, the class sets the private field that it uses for its IsTrackingViewState property to true . This indicates whether property change tracking has been turned on. When IsTrackingViewState is true , the StateBag class marks a StateItem as dirty when it is added to the StateBag or when its value is modified.

  • In its SaveViewState method, the StateBag class cycles through its contents and creates and returns two ArrayList s that respectively contain the keys and values of the items that are marked dirty.

  • In its LoadViewState method, StateBag performs the inverse of the operations it performed in SaveViewState . It uses the ArrayList s of keys and values to load the saved state into the appropriate StateItem s. (It is the responsibility of the user of a StateBag object to pass into LoadViewState the same object that the StateBag returned in SaveViewState .)

We'll now examine how the Control class implements default state management by delegating to its ViewState property. In Chapter 7, Chapter 8, and Chapter 9, you saw several examples of controls that use the ViewState property to maintain the state of simple properties. The following code fragments show the definition of the ViewState property and the implementation of the TrackViewState , SaveViewState , and LoadViewState methods in the Control class:

 privateStateBag_viewState; protectedvirtualStateBagViewState{ get{ if(_viewState!=null){ return_viewState; } _viewState=newStateBag(ViewStateIgnoresCase); if(IsTrackingViewState) _viewState.TrackViewState(); return_viewState; } } protectedvirtualvoidTrackViewState(){ if(_viewState!=null){ _viewState.TrackViewState(); } } protectedvirtualobjectSaveViewState(){ if(_viewState!=null){ return_viewState.SaveViewState(); } returnnull; } protectedvirtualvoidLoadViewState(objectsavedState){ if(savedState!=null){ ViewState.LoadViewState(savedState); } } 

When you save properties in ViewState , their state is automatically maintained for you. You can also store any other data in ViewState that your control needs across round-trips. As we mentioned in Chapter 7, you should store only those properties or data that need to maintain state in ViewState . Any types you save in ViewState must be serializable by LosFormatter . State tracking starts in TrackViewState , which is invoked after the Initialize phase. Items in ViewState added or modified before tracking begins are not marked dirty and thus are not saved in the serialized view state which is round-tripped to the client. This is important for efficiency. If you want to perform any initialization in your control, you should do so in your control's constructor or by overriding the OnInit method so that initial values are not serialized by the page framework. Note that a property stored in ViewState is marked dirty if it is assigned to after the Initialize phase, even if its value does not change. For example, if the Text property of a Label instance is initialized as label1.Text="sometext" , a subsequent property set of label1.Text="sometext" will cause the property to be marked dirty, although the value of the property did not change.

Next we'll look at custom state management for custom types that cannot be saved in ViewState .



Developing Microsoft ASP. NET Server Controls and Components
Developing Microsoft ASP.NET Server Controls and Components (Pro-Developer)
ISBN: 0735615829
EAN: 2147483647
Year: 2005
Pages: 183

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net