Optimizing ViewState usage: VB.NET approach with Database Storage

We have been experiencing issues with some massive viewstates causing slow page loads and “System.FormatException: Invalid length for a Base-64 char array or string”.

Capture

Based on http://www.componentworkshop.com/blog/2009/06/27/advanced-net-storing-viewstate-in-a-database we looked at moving the viewstate from the client to different options:

  • Into the session (disadvantage if your RAM on the server is limited)
  • Into a LOB file on the server (disadvantage on keeping the files per pages separate)
  • Into the Database.

In the end, we went with the database approach and quickly created the needed structure in our shared DB and implemented the code behind as a class:

App_Code

Public Class DatabasePageStatePersister
    Inherits PageStatePersister
    Private _GUID As String = ""

    Public Sub New(p As Page, GUID As String)
        MyBase.New(p)
        _GUID = GUID
    End Sub

    Public Overrides Sub Load()
        Dim ViewStateData As String = GetViewState(_GUID)
        Try
            Me.ViewState = Me.StateFormatter.Deserialize(ViewStateData)
        Catch ex As Exception
            Throw New exception("View State Data for GUID: " & _GUID)
        End Try

    End Sub

    Public Overrides Sub Save()
        Dim ViewStateData As String = Me.StateFormatter.Serialize(Me.ViewState)

        StoreViewState(_GUID, ViewStateData)
    End Sub


    Private _c As New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("HangfireCN").ConnectionString)

    Private Sub StoreViewState(guid As String, data As String)
        _c.Open()

        Try
            Dim cmd As New SqlCommand("StoreViewState", _c)
            cmd.CommandType = CommandType.StoredProcedure

            cmd.Parameters.Add(New SqlParameter("guid", SqlDbType.[Char], 128))
            cmd.Parameters("guid").Value = guid

            cmd.Parameters.Add(New SqlParameter("ViewStateData", SqlDbType.Text))
            cmd.Parameters("ViewStateData").Value = data

            cmd.ExecuteNonQuery()
        Finally
            _c.Close()
        End Try
    End Sub

    Private Function GetViewState(guid As String) As String
        Dim Data As String = ""

        _c.Open()

        Try
            Dim cmd As New SqlCommand("GetViewState", _c)
            cmd.CommandType = CommandType.StoredProcedure

            cmd.Parameters.Add(New SqlParameter("guid", SqlDbType.[Char], 128))
            cmd.Parameters("guid").Value = guid

            Dim r As SqlDataReader = cmd.ExecuteReader()

            If r.Read() Then
                Data = r("viewstatedata").ToString()
            End If
        Finally
            _c.Close()
        End Try

        Return Data
    End Function


End Class

Page code behind:

Private _PageStatePersister As PageStatePersister = Nothing

    Protected Overrides ReadOnly Property PageStatePersister As System.Web.UI.PageStatePersister
        Get
            If _PageStatePersister Is Nothing Then
                '_PageStatePersister = New MyHiddenFieldPageStatePersister(Me)
                Dim guid__1 As String = ""

                If Request("__DATABASE_VIEWSTATE") Is Nothing Then
                    Dim g As Guid = Guid.NewGuid()
                    guid__1 = g.ToString()
                    Session("__DATABASE_VIEWSTATE") = guid__1
                Else
                    guid__1 = Request("__DATABASE_VIEWSTATE").ToString()
                End If

                _PageStatePersister = New DatabasePageStatePersister(Me, guid__1)

                ScriptManager.RegisterHiddenField(Me, "__DATABASE_VIEWSTATE", guid__1)

            End If

            Return _PageStatePersister
        End Get
    End Property

Result:

Page size decrease by 223kb.
Capture

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s