|
Imports System.Web.UI
Imports System.IO
Imports System.Text
Imports System.Collections.Specialized
Namespace System.Web.Configuration.Providers
''' <summary>
''' Manages storage of viewstate object for an ASP.NET application in a ASP.NET session object.
''' </summary>
''' <remarks><para><pre>
''' RevisionHistory:
''' --------------------------------------------------------------------------------
''' Date Name Description
''' --------------------------------------------------------------------------------
''' 10/11/2006 Oleg Sobol Initial Creation, inspiration from http://www.eggheadcafe.com/articles/20040613.asp
''' 5/11/2007 Oleg Sobol Added ViewStateKeyName
'''
''' </pre></para></remarks>
Public Class SessionViewStateProvider
Inherits System.Web.UI.ViewStateProvider
' This uses an array and mod to cycle repeatedly through an array (so limited size)
' WARNING: When the user uses the "back" button on the browser, IE will not rerequest the page, so
' if the user posts again they need the viewstate to still be present on the server. Need to set the VIEW_STATE_NUM_PAGES
' to a tradeoff of number of back pages allowed and the amount of memory consumed by the viewstate kept per page.
Private Const NUM_PAGES_IN_MEMORY As Short = 5 ' Number of pages to keep viewstate for
Private _applicationName As String
Private _los As New LosFormatter
Private _numberOfPagesInMemory As Short
Private _pageCount As Long ' Number of pages seen by this customer
Private _viewStateKeyName As String = "__VIEWSTATE_KEY"
#Region " Properties "
Public Overrides Property ApplicationName() As String
Get
Return _applicationName
End Get
Set(ByVal value As String)
_applicationName = value
End Set
End Property
Public Overrides Property ViewStateKeyName() As String
Get
Return _viewStateKeyName
End Get
Set(ByVal value As String)
_viewStateKeyName = value
End Set
End Property
#End Region
Public Overloads Overrides Sub Initialize(ByVal name As String, ByVal config As NameValueCollection)
' Verify that config isn't null
If config Is Nothing Then Throw New ArgumentNullException("config")
' Assign the provider a default name if it doesn't have one
If String.IsNullOrEmpty(name) Then name = "SessionViewStateProvider"
' Add a default "description" attribute to config if the attribute doesn�t exist or is empty
If String.IsNullOrEmpty(config("description")) Then
config.Remove("description")
config.Add("description", "Session viewstate provider")
End If
' Call the base class's Initialize method
MyBase.Initialize(name, config)
' Initialize _applicationName
_applicationName = config("applicationName")
If String.IsNullOrEmpty(_applicationName) Then _applicationName = "/"
config.Remove("applicationName")
Dim numberOfPagesInMemory As String = config("numberOfPagesInMemory")
If String.IsNullOrEmpty(numberOfPagesInMemory) OrElse Not IsNumeric(numberOfPagesInMemory) Then
_numberOfPagesInMemory = NUM_PAGES_IN_MEMORY
Else
_numberOfPagesInMemory = CShort(numberOfPagesInMemory)
End If
config.Remove("numberOfPagesInMemory")
' Throw an exception if unrecognized attributes remain
If config.Count > 0 Then
Dim attr As String = config.GetKey(0)
If Not String.IsNullOrEmpty(attr) Then Throw New ViewStateProviderException("Unrecognized attribute: " + attr)
End If
End Sub
Public Overrides Function LoadPageState(ByVal pControl As UI.Control) As Object
Dim p As Page = CType(pControl, Page)
If Nothing = p.Request.Form(_viewStateKeyName) Then Return Nothing
Dim lRequestNumber As Long = 0
Try
lRequestNumber = Convert.ToInt64(p.Request.Form(_viewStateKeyName))
Catch
Return Nothing
End Try
' Could cycle though the array and make sure that the given request number is actually
' present (in case the array is not big enough). Much faster to just take the
' given request number and recalculate where it should be stored
Dim siIndex As Short = CType((lRequestNumber Mod _numberOfPagesInMemory), Short)
' load viewstate from serverside storage
Dim viewStates As String() ' Store for viewstates
Dim viewStateKey As String = GetViewStateKey()
If HttpContext.Current.Session.Item(viewStateKey) Is Nothing Then
viewStates = New String(_numberOfPagesInMemory) {}
HttpContext.Current.Session.Item(viewStateKey) = viewStates
Else
viewStates = CType(HttpContext.Current.Session.Item(viewStateKey), String())
End If
Dim viewState As String = viewStates(siIndex)
If viewState Is Nothing Then
Return Nothing
Else
Return _los.Deserialize(viewState)
End If
End Function
Public Overrides Sub SavePageState(ByVal pControl As UI.Control, ByVal viewState As Object)
' load viewstate from serverside storage
Dim viewStates As String() ' Store for viewstates
Dim viewStateKey As String = GetViewStateKey()
If HttpContext.Current.Session.Item(viewStateKey) Is Nothing Then
viewStates = New String(_numberOfPagesInMemory) {}
HttpContext.Current.Session.Item(viewStateKey) = viewStates
Else
viewStates = CType(HttpContext.Current.Session.Item(viewStateKey), String())
End If
Dim writer As StringWriter = New StringWriter()
_los.Serialize(writer, viewState)
System.Math.Min(System.Threading.Interlocked.Increment(_pageCount), _pageCount - 1)
Dim siIndex As Short = CType((_pageCount Mod _numberOfPagesInMemory), Short)
viewStates(siIndex) = writer.ToString
writer.Dispose()
' Need to register the viewstate hidden field
' (must be present or postback things don't work, we use in our case to store the request number)
CType(pControl, Page).ClientScript.RegisterHiddenField(_viewStateKeyName, _pageCount.ToString)
End Sub
''' <summary>
''' Gets the key for ViewState from each separate session based on SessionID
''' </summary>
''' <returns>ViewState key in Session storage</returns>
''' <remarks></remarks>
Private Function GetViewStateKey() As String
Return "__VIEWSTATE" & HttpContext.Current.Session.SessionID.ToString
End Function
End Class
End Namespace
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Oleg Sobol has been developing web applications in ASP.NET using VB.NET for the past three years. Currently working for a leading online higher education provider, developing new online initiatives and supporting multiple education platforms.