CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Brendan Tompkins [MVP]

Blog First. Ask Questions Later.

Simplified State Management with StateClassBase

OBSOLETE CONTENT
The author of this post has determined that this content is obsolete. Use at your own risk! Blog posts are a point-in-time snapshot of the blogger's thinking and should not be assumed to represent this blogger's current opinions. This post was left up for historical purposes.

State management in web applications can be tricky.  ASP.NET and the .NET framework offers some help in this regard, with controls that can maintain their own state.  Often, however, you may find yourself storing things in Session or ViewState to maintain other stateful properties of your applications.  You've really got two options for doing this 1) Store objects individually in view state, or 2) Create a state class object that exposes your state objects as typed public properties.  There's really no question here as to which is the better option.  With #1 you have to manage hash keys, and box and unbox your objects.  You also have no way of simply re-setting state, or restoring state from persistent storage, such as a database.  Mark DiGiovanni has blogged about the advantages of maintaining state in one place.

So, how do you go about this?  I've developed a method of doing this that I'm pretty happy with.  It involves the use of a base State class (StateClassBase) that is meant to be sub-classed when you wish to maintain state.  This class will handle storing state in Session or ViewState, depending on your implementation.  Here's the class. (I've removed comments for simplicity)

[Serializable()]
public class StateClassBase
{
      
private string _stateKey;

       public StateClassBase(string stateKey)
       {
           _stateKey = stateKey; 
       }

       public virtual object StateRestore(System.Web.UI.StateBag ViewState) {
         
if(ViewState[_stateKey] != null) return ViewState[_stateKey];
          
else return null;
       }

        public virtual object StateRestore(System.Web.SessionState.HttpSessionState ViewState) {
          
if(ViewState[_stateKey] != null) return ViewState[_stateKey];
          
else return null;
        }

         public virtual void StateStore(System.Web.UI.StateBag ViewState) {
             ViewState[_stateKey] =
this;
         }

        
public virtual void StateStore(System.Web.SessionState.HttpSessionState ViewState) {
             ViewState[_stateKey] =
this;
         }

         public virtual void StateRemove(System.Web.UI.StateBag ViewState) {
            ViewState[_stateKey] =
null;
         }
        
          
public virtual void StateRemove(System.Web.SessionState.HttpSessionState ViewState) {
            
ViewState[_stateKey] = null;
         
}
}

Pretty simple, huh?  I've found that it's best for each control that needs to store state to store its own state using a derived state class object.  This way, I can reset state for one part of the application without affecting another.  If I need the state to persist only for the lifetime of the page, I pass the current StateBag object (ViewState) to the StateClassBase methods.  If I need more persistent state, or if I'm storing a lot of data, I pass a HttpSessionState object (Session). 

The following design pattern seems to work best for my purposes.  The example is for maintaining page index and sort expressions for a DataGrid.

  1. Create a derived StateClass object

    public class DataGridPageState : VIT.Common.Classes.StateClassBase
    {
       private int m_intCurrentPageIndex = 0;
       private string m_strCurrentSortExpression;

       public DataGridPlusPageState(string uniqueID) : base(uniqueID + "DATA_GRID_PAGE_STATE"){}

       public int CurrentPageIndex
       {
          get {return m_intCurrentPageIndex; }
         
    set {m_intCurrentPageIndex = value; }
       }

       public string SortExpression
       {
       
    get {return m_strCurrentSortExpression; }
       
    set {m_strCurrentSortExpression = value; }
       }

    }

  2. Create a private class-level member instance of this object

    private DataGridPageState m_pageState;

  3. In the page or control's OnInit() method, restore this member instance from your state store

    this.m_pageState = (DataGridPageState) new DataGridPageState(this.UniqueID).StateRestore(this.Session);
    if(this.m_pageState == null) this.m_pageState = new DataGridPageState(this.UniqueID);

  4. Call the StateStore method after setting any property on the object.   This example is from the event handler for the DataGrid's PageChanged method.

    this.m_pageState.CurrentPageIndex = e.NewPageIndex;
    this.m_pageState.StateStore(this.Session);
  5. When you need access to your state, simply use your member variable, which should always contain the current state, like so:

    this.DataGridPlus1.PageSize = m_pageState.PageSize;

That's it!  You now have your state in a nice package with typed versions of your state objects to work with.  You can use this pattern from any control that has access to the System.Web namespace. 

-Brendan



Comments

TrackBack said:

# February 2, 2005 4:05 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Brendan Tompkins

Brendan has been programming with .NET since the first public beta and is owner and operator of Port Technology Services, a consultancy company providing .NET application development services to the Maritime industry. In July, 2007, he was awarded the Microsoft MVP award for ASP.NET. He's also a proud co-founder of failed .COM startup Intrinsigo, and has had a hand in the failure of numerous other businesses. He currently runs CodeBetter.Com and Devlicio.us, and lives in Norfolk, Virgina with his wife Tiara and son Ian.

View Brendan's profile on LinkedIn

Check out Devlicio.us!

Our Sponsors

This Blog

Syndication

News

MVP
Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 License.