存储位置优化——把视图状态信息保存在服务端而非客户端

精贴 置顶
400 0

 存储位置优化——把视图状态信息保存在服务端而非客户端

 

本文节选自《庖丁解牛:纵向切入ASP.NET 3.5控件和组件开发技术》一书

      视图状态信息默认情况下是存储在客户端的,不占用服务端资源(这里是指持续地占用服务器资源一定时间,视图状态只是在页面呈现时,服务端正反向解析视图状态内容占用一会服务器内存,当页面呈现完成后则会把视图存储到页面上的隐藏控件域中)。当页面结构比较复杂时,会导致视图信息字节数比较大,则会产生带宽瓶颈。为了解决这个问题我们可以选择把视图信息存储到服务器端,或数据库中,或文件等存储介质。这一节我们就以把视图状态存储到服务端Session中为例,说明其实现方法。
新建一个页面SessionPageStatePersister.aspx,页面中的内容仍然使用前面的控件状态控件的测试页面内容,设置好页面内容后,在后台代码中重写基类Page的PageStatePersister属性,如下所示:
/// <summary>
/// 获得本书更多内容,请看:
/// http://blog.csdn.net/ChengKing/archive/2008/08/18/2792440.aspx
/// </summary>
public partial class Page_SessionPageStatePersister : System.Web.UI.Page
{
    protected override PageStatePersister PageStatePersister
    {
        get
        {
            return new SessionPageStatePersister(this);
        }
    }
}
为了更容易理解,下面是Page对该属性的系统默认实现源代码:
protected virtual PageStatePersister PageStatePersister
{
    get
    {
        if (this._persister == null)
        {
            PageAdapter pageAdapter = this.PageAdapter;
            if (pageAdapter != null)
            {
                this._persister = pageAdapter.GetStatePersister();
            }
            if (this._persister == null)
            {
                this._persister = new HiddenFieldPageStatePersister(this);
            }
        }
        return this._persister;
    }
}
ASP.NET的默认持久性机制是使用HiddenFieldPageStatePersister类将视图状态存储在客户端,即系统默认实现是在属性PageStatePersister中返回HiddenFieldPageStatePersister类实例,表示存储在客户端的隐藏域中。上面我们重写该属性,返回SessionPageStatePersister类实例,SessionPageStatePersister类表示在Web服务器Session会话中存储ASP.NET页视图状态。
OK,运行一下页面,并查看一下它的隐藏域视图信息,会发现__VIEWSTATE由原来的:
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value= "/wEPDwUJNzIxMjkzNTM2D2QWAgIDD2QWBAIBDw8WAh4OVGV4dF9WaWV3U3RhdGUFIuaIkeaYr+eUqFZpZXdTdGF0ZeWuueWZqOWtmOWCqOeahCFkZAIHDw8WAh4EVGV4dAWQBHRoaXMuQ29udHJvbFN0YXRlQ29udHJvbDEuVGV4dF9Ob1ZpZXdTdGF0ZeWxnuaApyDmsqHmnInkv53lrZjmjqfku7bnirbmgIEgPEltZyBzcmM9Jy4uXEltYWdlc1xKUy5qcGcnIC8+ICA8YnI+PGJyPnRoaXMuQ29udHJvbFN0YXRlQ29udHJvbDEuVGV4dF9WaWV3U3RhdGXlsZ7mgKcg5bey57uP5L+d5a2Y5LqG5o6n5Lu254q25oCBIDxJbWcgc3JjPScuLlxJbWFnZXNcWEwuanBnJyAvPiAgPGJyPjxicj50aGlzLkNvbnRyb2xTdGF0ZUNvbnRyb2wxLkZhY2VTdHlsZeWxnuaApy5PSyDlt7Lnu4/kv53lrZjkuobmjqfku7bnirbmgIEgPEltZyBzcmM9Jy4uXEltYWdlc1xYTC5qcGcnIC8+ICA8YnI+PGJyPnRoaXMuQ29udHJvbFN0YXRlQ29udHJvbDEuRmFjZVN0eWxlLkJhY2tDb2xvciDlt7Lnu4/kv53lrZjkuobmjqfku7bnirbmgIEsIOeep++8jOaIkeeahOminOiJsuWwseaYr+S/neWtmOeahOminOiJsiA8SW1nIHNyYz0nLi5cSW1hZ2VzXFhMLmpwZycgLz4gIDxJbWcgc3JjPScuLlxJbWFnZXNcQkcuanBnJyAvPiA8YnI+PGJyPmRkGAEFFENvbnRyb2xTdGF0ZUNvbnRyb2wxDw8PFgIfAAUi5oiR5piv55SoVmlld1N0YXRl5a655Zmo5a2Y5YKo55qEIWQUKwACFgQeCUJhY2tDb2xvcgoAHgRfIVNCAghnZHweEc0h/1gIsxczc2fHdmLTQy1x" />
变为现在的:
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value= "/wEPaA8FDzhjYTlhMjI1ZDY2NTQ3MxgBBRRDb250cm9sU3RhdGVDb250cm9sMQ8PDxYCHg5UZXh0X1ZpZXdTdGF0ZQUi5oiR5piv55SoVmlld1N0YXRl5a655Zmo5a2Y5YKo55qEIWQUKwACFgQeCUJhY2tDb2xvcgoAHgRfIVNCAghnZNiSxDj0eWw88GLxQrKC0IucFKmW" />
另外,这里的HiddenFieldPageStatePersister和SessionPageStatePersister都是继承基类 System.Web.UI.PageStatePersister,该基类允许自定义持久化机制,如果既不想存储到客户端隐藏域中,也不想存储到Session中,可以定义该类的派生类,实现自定义持久化机制。在6.8.2小节有一个派生System.Web.UI.PageStatePersister 类的例子。
除了使用重写基类Page的PageStatePersister属性实现指定持久化类对象外,还可以通过实现System.Web.UI.Adapters.PageAdapter类的页配器实现同样功能。PageAdapter类是一个抽象类,可以修改网页以适应特定的浏览器,并提供所有页面适配器可直接或间接继承的基类。下面是一个自定义页适配器的例子:
/// <summary>
/// 获得本书更多内容,请看:
/// http://blog.csdn.net/ChengKing/archive/2008/08/18/2792440.aspx
/// </summary>
public class SessionPageAdapter : System.Web.UI.Adapters.PageAdapter
{
    public override PageStatePersister GetStatePersister()
    {
        return new SessionPageStatePersister(this.Page);
    }
}
然后在站点下面添加App_Browsers目录,并添加一个文件名称为SessionPageAdapter.browser的文件,内容如下:
<browsers>
    //… …
    <browser refID="Default">
      <controlAdapters>
        <adapter controlType="System.Web.UI.Page" adapterType="KingControls. SessionPageAdapter" />
      </controlAdapters>
    </browser>  
</browsers>
运行一下页面,也会发现得到与之前相同的效果。这两种方法都能够在服务器Session中存储视图信息。不同的一点是后面这种方式影响到了整个站点下面的所有页面。
Session一般用于存储特定于单独会话的短期信息,比存储到客户端隐藏域中方式要安全得多。但这种方式要占用服务器内存,因此在客户端比较多的情况下不要在Session中存储大量的信息。

  • 没有任何评论
今日天气 ···

···

···

···

热门排行
CSS cursor鼠标样式一览表 2012/6/25
.NET后台写JS代码 2011/11/3
网站地址多出jdfwkey的问题解析及... 2010/8/25
百度、google、Yahoo网站地图制作... 2011/1/30
数据库xxx的日志已满,请备份该数... 2013/7/19
<a>标签的伪类书写顺序问题... 2010/9/4
CEO名言 2010/8/31
什么是长尾关键词? 2010/9/24
Mysql 主从数据库同步 2010/9/12
用ASP实现网页BBS 2010/11/1
博主推荐
网站title标题如何正确修改不会被... 2013/8/26
ASP .NET MYSQL 的简单分页 并不... 2013/8/19
网站有弹窗广告这样的站点,百度... 2013/8/17
做淘宝SEO优化需要注意的8大问题 2013/8/17
淘宝网怎么做SEO优化 2013/8/17
站长们要学习的“苍井空精神” 2013/8/17
苹果公司今日发布了iOS 7第五个开... 2013/8/7
小米1刷V5系统WIFI不能连接解决办... 2013/8/1
本博客手机版上线咯!会员后台也... 2013/7/31
Win7系统环境安装配置PHP开发环境... 2013/7/29
随便看看
Java使用过滤器控制用户访问权限 2013/6/26
php计算数组中值出现的次数 2010/10/11
JS过滤url参数特殊字符的方法 2013/11/15
Windows 7特色功能体验:优化篇 2011/1/20
.net用母版页和内容页实现动态Ti... 2013/8/22
VS2008切换设计视图假死机情况,以... 2013/5/3
位运算符 2010/10/18
web开发中如何在IE后退时设置网页... 2013/9/6
微信公众平台开发 ACCESS TOKEN 2013/12/17
如何在webform.aspx.cs中控制用户... 2010/9/11
北京 上海 杭州 深圳 广州 成都