• 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的情况.
  • 相关阅读:
    win7下iis中配置php.ini文件
    editplus快捷键大全
    树和二叉树的存储结构的实现(C/C++实现)
    CTF---编程入门第一题 循环
    CTF---Web入门第九题 FALSE
    CTF---Web入门第八题 Guess Next Session
    CTF---Web入门第七题 猫抓老鼠
    CTF---Web入门第六题 因缺思汀的绕过
    CTF---Web入门第五题 貌似有点难
    CTF---Web入门第四题 Forms
  • 原文地址:https://www.cnblogs.com/shiningrise/p/851404.html
Copyright © 2020-2023  润新知