问题
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.
I'd love to hear some comments and any tips that people might have.
Public Class ViewState
''' <summary>
''' Saves the state to the users session
''' </summary>
''' <param name="viewState">The viewstate object to serialize</param>
''' <param name="NoSerialize"></param>
''' <returns>Returns the KEY of the string that was saved.</returns>
''' <remarks></remarks>
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
''' <summary>
''' Returns a deserialized copy of the viewstate object
''' </summary>
''' <param name="SQLSTATE"></param>
''' <param name="NoSerialize"></param>
''' <returns></returns>
''' <remarks></remarks>
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
''' <summary>
''' AJAX Viewstate
''' Saves the state to the users session
''' </summary>
''' <param name="viewState">The viewstate object to serialize</param>
''' <param name="VSID">The ID that the page uses to find the viewstate item</param>
''' <param name="NoSerialize"></param>
''' <returns>Returns the KEY of the string that was saved.</returns>
''' <remarks></remarks>
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
''' <summary>
''' Gets the string representing the cached viewstate object.
''' </summary>
''' <param name="VSID">Use this to override the session VSID property and use your own.</param>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property CacheString(Optional ByVal VSID As Integer = 0) As String
Get
If VSID = 0 Then
Return "ViewState" & HttpContext.Current.Session("VSID")
Else
Return "ViewState" & VSID
End If
End Get
End Property
End Class
The following code goes in the code behind for your asp.net page:
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
回答1:
Before you roll your own code to persist the viewstate to the session, have you tried the built in functionality?
protected override PageStatePersister PageStatePersister
{
get
{
return new SessionPageStatePersister(this);
}
}
(C# version shown). Maybe this will solve your back button issue?
Edit to answer comment: I think this is the VB equivalent:
Public Overrides Function GetStatePersister() As PageStatePersister
Return New SessionPageStatePersister(Page)
End Function 'GetStatePersister
I don't know how this handles the back-button, but I believe that it stores up to 10 states per page.
来源:https://stackoverflow.com/questions/271269/ideas-for-how-to-deal-with-viewstate-when-using-asp-net-ajax-and-update-panels