DNN性能优化方案系列(2)Page State Persistence

我在<<DNN性能优化方案系列(1)概述 >>说明DNN对性能优化做的努力,Page State Persistence的保存方法是其中一个措施之一.
下面来看下DNN4.5.5的实现.
先看 DotNetNuke_04.05.05_Source\Library\Components\Framework\PageBase.vb
#Region "Protected Properties"

        
''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' PageStatePersister returns an instance of the class that will be used to persist the Page State
        ''' </summary>
        ''' <returns>A System.Web.UI.PageStatePersister</returns>
        ''' <history>
        '''     [cnurse]        11/30/2005    Created
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Protected Overrides ReadOnly Property PageStatePersister() As System.Web.UI.PageStatePersister
            
Get
                
'Set ViewState Persister to default (as defined in Base Class)
                Dim _persister As PageStatePersister = MyBase.PageStatePersister
                
If Not DotNetNuke.Common.Globals.HostSettings("PageStatePersister"Is Nothing Then
                    
Select Case DirectCast(DotNetNuke.Common.Globals.HostSettings("PageStatePersister"), String)
                        
Case "M"
                            _persister 
= New CachePageStatePersister(Me)
                        
Case "D"
                            _persister 
= New DiskPageStatePersister(Me)
                    
End Select
                
End If
                
Return _persister
            
End Get
        
End Property
#End Region

其中

Select Case DirectCast(DotNetNuke.Common.Globals.HostSettings("PageStatePersister"), String)
         
Case "M"   '选择将页面状态持久化保存于内存,M即memery首字母
                   _persister = New CachePageStatePersister(Me)
         
Case "D"  '选择将页面状态持久化保存于硬盘,D即Disk首字母,不过在主机设置里面似乎没有这个选项
                   _persister = New DiskPageStatePersister(Me)
           
End Select
CachePageStatePersister.vb
Imports System.Text

Namespace DotNetNuke.Framework

    
''' -----------------------------------------------------------------------------
    ''' Namespace:  DotNetNuke.Framework
    ''' Project:    DotNetNuke
    ''' Class:      CachePageStatePersister
    ''' -----------------------------------------------------------------------------
    ''' <summary>
    ''' CachePageStatePersister provides a cache based page state peristence mechanism
    ''' </summary>
    ''' <history>
    '''        [cnurse]    11/30/2006    documented
    ''' </history>
    ''' -----------------------------------------------------------------------------
    Public Class CachePageStatePersister
        
Inherits PageStatePersister

        
''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' Creates the CachePageStatePersister
        ''' </summary>
        ''' <history>
        '''     [cnurse]        11/30/2006    Documented
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Public Sub New(ByVal page As Page)
            
MyBase.New(page)
        
End Sub


        
''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' Loads the Page State from the Cache
        ''' </summary>
        ''' <history>
        '''     [cnurse]        11/30/2006    Documented
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Public Overrides Sub Load()

            
' Get the cache key from the web form data
            Dim key As String = TryCast(Page.Request.Params("__VIEWSTATE_CACHEKEY"), String)

            
'Abort if cache key is not available or valid
            If String.IsNullOrEmpty(key) Or Not key.StartsWith("VS_"Then
                
Throw New ApplicationException("Missing vaild __VIEWSTATE_CACHEKEY")
            
End If

            
Dim state As Pair = TryCast(DataCache.GetPersistentCacheItem(key, GetType(Pair)), Pair)

            
If Not state Is Nothing Then
                
'Set view state and control state
                ViewState = state.First
                ControlState 
= state.Second
            
End If

        
End Sub


        
''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' Saves the Page State to the Cache
        ''' </summary>
        ''' <history>
        '''     [cnurse]        11/30/2006    Documented
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Public Overrides Sub Save()

            
'No processing needed if no states available
            If ViewState Is Nothing And ControlState Is Nothing Then
                
Exit Sub
            
End If

            
Dim key As New StringBuilder()
            
Dim _PortalSettings As PortalSettings = PortalController.GetCurrentPortalSettings()
            
Dim TabId As Integer = _PortalSettings.ActiveTab.TabID

            
'Generate a unique cache key
            With key
                .Append(
"VS_")
                .Append(
IIf(Page.Session Is Nothing, Guid.NewGuid().ToString(), Page.Session.SessionID))
                .Append(
"_")
                .Append(TabId)
            
End With


            
'Save view state and control state separately
            Dim state As New Pair(ViewState, ControlState)

            
'Add view state and control state to cache
            DataCache.SetCache(key.ToString(), state, Nothing, DateTime.Now.AddMinutes(15), System.Web.Caching.Cache.NoSlidingExpiration, True)

            
'Register hidden field to store cache key in
            Page.ClientScript.RegisterHiddenField("__VIEWSTATE_CACHEKEY", key.ToString())

        
End Sub


    
End Class


End Namespace


继承PageStatePersister必须重载Load与Save
DNN将ViewState保存在内存,它将用于保存的Key保存的页面,用于从内存存取ViewState
Page.ClientScript.RegisterHiddenField("__VIEWSTATE_CACHEKEY", key.ToString())
生成一个隐藏域
<input type="hidden" name="__VIEWSTATE_CACHEKEY" id="__VIEWSTATE_CACHEKEY" value="VS_yjp0hlrgns3sqirbw0hsci45_36" />
此Key生成方法如下
With key
                .Append("VS_")
                .Append(IIf(Page.Session Is Nothing, Guid.NewGuid().ToString(), Page.Session.SessionID))
                .Append("_")
                .Append(TabId)
            End With

并设置Cache过期时间为15分钟
DataCache.SetCache(key.ToString(), state, Nothing, DateTime.Now.AddMinutes(15), System.Web.Caching.Cache.NoSlidingExpiration, True)
如果15分钟后页面才回传就会
Throw New ApplicationException("Missing vaild __VIEWSTATE_CACHEKEY")
就是这个页面的所有ViewState已经全部丢失.
这个Bug怎么处理,DNN不知有没有触觉的办法.我还没发现,或者目前根本还没解觉.
有好办法的同仁请提示下.

DiskPageStatePersister.vb

Imports System.IO
Imports System.Text

Namespace DotNetNuke.Framework

    
''' -----------------------------------------------------------------------------
    ''' Namespace:  DotNetNuke.Framework
    ''' Project:    DotNetNuke
    ''' Class:      DiskPageStatePersister
    ''' -----------------------------------------------------------------------------
    ''' <summary>
    ''' DiskPageStatePersister provides a disk (stream) based page state peristence mechanism
    ''' </summary>
    ''' <history>
    '''        [cnurse]    11/30/2006    documented
    ''' </history>
    ''' -----------------------------------------------------------------------------
    Public Class DiskPageStatePersister
        
Inherits PageStatePersister

        
''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' Creates the DiskPageStatePersister
        ''' </summary>
        ''' <history>
        '''     [cnurse]        11/30/2006    Documented
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Public Sub New(ByVal page As Page)
            
MyBase.New(page)
        
End Sub


        
''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' The CacheDirectory property is used to return the location of the "Cache"
        ''' Directory for the Portal
        ''' </summary>
        ''' <remarks>
        ''' </remarks>
        ''' <history>
        '''   [cnurse] 11/30/2006  Created
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Public ReadOnly Property CacheDirectory() As String
            
Get
                
Return PortalController.GetCurrentPortalSettings.HomeDirectoryMapPath & "Cache"
            
End Get
        
End Property


        
''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' The StateFileName property is used to store the FileName for the State
        ''' </summary>
        ''' <remarks>
        ''' </remarks>
        ''' <history>
        '''   [cnurse] 11/30/2006  Created
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Public ReadOnly Property StateFileName() As String
            
Get
                
Dim key As New StringBuilder()
                
With key
                    .Append(
"VIEWSTATE_")
                    .Append(Page.Session.SessionID)
                    .Append(
"_")
                    .Append(Page.Request.RawUrl)
                
End With
                
Return CacheDirectory & "\" & CleanFileName(key.ToString) & ".txt"
            
End Get
        
End Property


        
''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' Loads the Page State from the Cache
        ''' </summary>
        ''' <history>
        '''     [cnurse]        11/30/2006    Documented
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Public Overrides Sub Load()

            
Dim reader As StreamReader = Nothing

            
' Read the state string, using the StateFormatter.
            Try
                reader 
= New StreamReader(StateFileName)

                
Dim serializedStatePair As String = reader.ReadToEnd

                
Dim formatter As IStateFormatter = Me.StateFormatter

                
' Deserialize returns the Pair object that is serialized in
                ' the Save method.      
                Dim statePair As Pair = CType(formatter.Deserialize(serializedStatePair), Pair)

                ViewState 
= statePair.First
                ControlState 
= statePair.Second
            
Finally
                
If Not reader Is Nothing Then
                    reader.Close()
                
End If
            
End Try

        
End Sub



        
''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' Saves the Page State to the Cache
        ''' </summary>
        ''' <history>
        '''     [cnurse]        11/30/2006    Documented
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Public Overrides Sub Save()

            
'No processing needed if no states available
            If ViewState Is Nothing And ControlState Is Nothing Then
                
Exit Sub
            
End If

            
If Not (Page.Session Is NothingThen
                
If Not Directory.Exists(CacheDirectory) Then
                    Directory.CreateDirectory(CacheDirectory)
                
End If

                
' Write a state string, using the StateFormatter.
                Dim writer As New StreamWriter(StateFileName, False)

                
Dim formatter As IStateFormatter = Me.StateFormatter

                
Dim statePair As New Pair(ViewState, ControlState)

                
Dim serializedState As String = formatter.Serialize(statePair)

                writer.Write(serializedState)
                writer.Close()
            
End If
        
End Sub

    
End Class


End Namespace

在源码中看到的保存于盘硬的,没有过期这回事,但总不能让那些没用的文件一直留着,要有个删除的办法.但DNN中似乎还没处理这个.
还有这个Key问题,

        ''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' The StateFileName property is used to store the FileName for the State
        ''' </summary>
        ''' <remarks>
        ''' </remarks>
        ''' <history>
        '''   [cnurse] 11/30/2006  Created
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Public ReadOnly Property StateFileName() As String
            
Get
                
Dim key As New StringBuilder()
                
With key
                    .Append(
"VIEWSTATE_")
                    .Append(Page.Session.SessionID)
                    .Append(
"_")
                    .Append(Page.Request.RawUrl)
                
End With
                
Return CacheDirectory & "\" & CleanFileName(key.ToString) & ".txt"
            
End Get
        
End Property
与比CachePageStatePersister.vb不周到的地方是他似乎没考虑Page禁用Session的情况.
原文地址:https://www.cnblogs.com/shiningrise/p/851404.html