title: Ideas for how to deal with viewstate when using ASP.NET AJAX and update panels
body: <p>Here is a class that I wrote to solve some issues that I was having with viewstate.  It stores the info in the users session and increments a value to track which state to show.  The difficulty is that there is no support for the back button.  The reason I originally had this was that before AJAX came along the viewstate was being send down to the client instead of being stored on the server.  I figured that by storing it on the server i could make the client experience much richer.  Now with distributed caching through projects like velocity this could be stored in a cache.</p>
  
  <p>I'd love to hear some comments and any tips that people might have.</p>
  
  <pre><code>Public Class ViewState
      ''' &lt;summary&gt;
      ''' Saves the state to the users session
      ''' &lt;/summary&gt;
      ''' &lt;param name="viewState"&gt;The viewstate object to serialize&lt;/param&gt;
      ''' &lt;param name="NoSerialize"&gt;&lt;/param&gt;
      ''' &lt;returns&gt;Returns the KEY of the string that was saved.&lt;/returns&gt;
      ''' &lt;remarks&gt;&lt;/remarks&gt;
      Function SaveState(ByVal viewState As Object, Optional ByVal NoSerialize As Boolean = False)
          HttpContext.Current.Session("VSID") = HttpContext.Current.Session("VSID") + 1
          If NoSerialize Then
              HttpContext.Current.Session(CacheString) = viewState
          Else
              Dim Format As New LosFormatter
              Dim Writer As New System.IO.StringWriter
              Format.Serialize(Writer, viewState)
              HttpContext.Current.Session(CacheString) = Writer.ToString
          End If
          Return HttpContext.Current.Session("VSID")
      End Function
      ''' &lt;summary&gt;
      ''' Returns a deserialized copy of the viewstate object
      ''' &lt;/summary&gt;
      ''' &lt;param name="SQLSTATE"&gt;&lt;/param&gt;
      ''' &lt;param name="NoSerialize"&gt;&lt;/param&gt;
      ''' &lt;returns&gt;&lt;/returns&gt;
      ''' &lt;remarks&gt;&lt;/remarks&gt;
      Function LoadState(ByVal SQLSTATE, Optional ByVal NoSerialize = False) As Object
          If NoSerialize Then
              If Not HttpContext.Current.Session(CacheString(SQLSTATE)) Is Nothing Then
                  Return HttpContext.Current.Session(CacheString(SQLSTATE))
              Else
                  HttpContext.Current.Trace.Warn("No ViewState Object Found")
              End If
          Else
              Dim Format As New LosFormatter
              If Not HttpContext.Current.Session(CacheString(SQLSTATE)) Is Nothing Then
                  Return Format.Deserialize(HttpContext.Current.Session(CacheString(SQLSTATE)))
              Else
                  HttpContext.Current.Trace.Warn("No ViewState Object Found")
              End If
          End If
      End Function
      ''' &lt;summary&gt;
      ''' AJAX Viewstate
      ''' Saves the state to the users session
      ''' &lt;/summary&gt;
      ''' &lt;param name="viewState"&gt;The viewstate object to serialize&lt;/param&gt;
      ''' &lt;param name="VSID"&gt;The ID that the page uses to find the viewstate item&lt;/param&gt;
      ''' &lt;param name="NoSerialize"&gt;&lt;/param&gt;
      ''' &lt;returns&gt;Returns the KEY of the string that was saved.&lt;/returns&gt;
      ''' &lt;remarks&gt;&lt;/remarks&gt;
      Function SaveState(ByVal viewState As Object, ByVal VSID As String, Optional ByVal NoSerialize As Boolean = False)
          HttpContext.Current.Session("VSID") = HttpContext.Current.Session("VSID") + 1
          If NoSerialize Then
              If VSID = "" Then
                  HttpContext.Current.Session(CacheString) = viewState
                  Return HttpContext.Current.Session("VSID")
              Else
                  HttpContext.Current.Session("VSID") = HttpContext.Current.Session("VSID") + 1
                  HttpContext.Current.Session(CacheString) = viewState
                  HttpContext.Current.Session(CacheString(VSID)) = viewState
                  Return HttpContext.Current.Session("VSID")
              End If
          Else
              Dim Format As New LosFormatter
              Dim Writer As New System.IO.StringWriter
              Format.Serialize(Writer, viewState)
              If VSID = "" Then
                  HttpContext.Current.Session("VSID") = HttpContext.Current.Session("VSID") + 1
                  HttpContext.Current.Session(CacheString) = Writer.ToString
                  Return HttpContext.Current.Session("VSID")
              Else
                  HttpContext.Current.Session("VSID") = HttpContext.Current.Session("VSID") + 1
                  HttpContext.Current.Session(CacheString) = Writer.ToString
                  HttpContext.Current.Session(CacheString(VSID)) = Writer.ToString
                  Return HttpContext.Current.Session("VSID")
              End If
          End If
      End Function
      ''' &lt;summary&gt;
      ''' Gets the string representing the cached viewstate object.
      ''' &lt;/summary&gt;
      ''' &lt;param name="VSID"&gt;Use this to override the session VSID property and use your own.&lt;/param&gt;
      ''' &lt;value&gt;&lt;/value&gt;
      ''' &lt;returns&gt;&lt;/returns&gt;
      ''' &lt;remarks&gt;&lt;/remarks&gt;
      Public ReadOnly Property CacheString(Optional ByVal VSID As Integer = 0) As String
          Get
              If VSID = 0 Then
                  Return "ViewState" &amp; HttpContext.Current.Session("VSID")
              Else
                  Return "ViewState" &amp; VSID
              End If
          End Get
      End Property
  End Class
  </code></pre>
  
  <p>The following code goes in the code behind for your asp.net page:</p>
  
  <pre><code>Protected Overrides Sub SavePageStateToPersistenceMedium(ByVal viewState As Object)
          Dim VState As New ViewState
          If String.IsNullOrEmpty(Request.Form("__SQLVIEWSTATE")) = False Then
              RegisterHiddenField("__SQLVIEWSTATE", VState.SaveState(viewState, Request.Form("__SQLVIEWSTATE")))
          Else
              RegisterHiddenField("__SQLVIEWSTATE", VState.SaveState(viewState))
          End If
      End Sub
      Protected Overrides Function LoadPageStateFromPersistenceMedium() As Object
          Dim VState As New ViewState
          Return VState.LoadState(Request.Form("__SQLVIEWSTATE"))
      End Function
  </code></pre>