BLACK JACK

Get busy living, or get busy dying.
posts - 24, comments - 199, trackbacks - 30, articles - 3

导航

公告

Server Side ViewState 在服务器端存贮ViewState (ASP.NET 2.0)

Posted on 2005-11-25 17:37 J. Lin 阅读(...) 评论(...) 编辑 收藏
View State 在 Asp.Net 的 postback 机制中有着举足轻重的地位,但是在带宽紧张的环境下(比如跨国访问)庞大的hiddenfield 往往成为系统瓶颈。有什么办法可以在服务器端保存View State吗?答案是肯定的。

方法一:
The Code Project 上的一篇文章Keep ASP.NET ViewState out of ASPX Page for Performance Improvement ,采用override Page 的SavePageStateToPersistenceMediumLoadPageStateFromPersistenceMedium 两个方法,把View State存储在Session或cache中。
但是这种方法总显的过于繁琐,有没有什么更简便的方法呢?


方法二:
ASP.NET 2.0 Quick Start中有这么一段
    Page-state, (the cumulative view-state and control-state for the controls and the page) is typically persisted to the page's response, using the HiddenFieldStatePersister (it is the VIEWSTATE hidden field). You can override the PageStatePersister on the Page for custom persistence however. Given the adaptive nature of controls to the requesting device, some devices may not handle significant amounts of data that are typically 'round-tripped'. Through the PageAdapter configured for a device, the state can be persisted to alternative sources. ASP.NET 2.0 defines two page state persisters, HiddenFieldPageStatePersister and SessionPageStatePersister.

其实ASP.NET 2.0中已经内置了把ViewState存贮在Session中的SessionPageStatePersister,只要override Page的PageStatePersister属性,把返回HiddenFieldPageStatePersister 改为返回SessionPageStatePersister就可以了。这样实在是很方便哦。

但是我又发现了一件很不爽的事情,我们来看一下Page.PageStatePersister的代码:
protected virtual PageStatePersister PageStatePersister
{
      
get
      {
            
if (this._persister == null)
            {
                  PageAdapter adapter1 
= this.PageAdapter;
                  
if (adapter1 != null)
                  {
                        
this._persister = adapter1.GetStatePersister();
                  }
                  
if (this._persister == null)
                  {
                        
this._persister = new HiddenFieldPageStatePersister(this);
                  }
            }
            
return this._persister;
      }
}
我们虽然可以重载PageStatePersister属性,却不能修改_persister。在Page的其他很多地方是直接调用_persister的。这样可能会造成某种程度的不一致。
有什么办法呢?注意到上面的那个PageAdapter吗?我们就拿它开刀。


方法三:
首先写一个我们自己的PageAdapter
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;

namespace my
{
    
public class PageStateAdapter : System.Web.UI.Adapters.PageAdapter
    {
        
public override PageStatePersister GetStatePersister()
        {
            
return new SessionPageStatePersister(this.Page);
        }
    }
}

然后在站点下添加App_Browsers目录,并在目录下添加PageStateAdapter.browser
<browsers>
    
<browser refID="Default">
        
<controlAdapters>
           
<adapter controlType="System.Web.UI.Page" adapterType="my.PageStateAdapter" />
        
</controlAdapters>
    
</browser>
</browsers>

好了我们的Server Side View State完成了,你可以比较一下前后生成的文件大小,越是复杂的页面效果越明显。当然这是以牺牲服务器性能为代价的。需要注意的是:所谓的server side,还要依赖于站点的session的存贮方式是如何配置的,不过这不在本文的讨论范围之内。