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

精贴 置顶
1311 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中存储大量的信息。

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

···

···

···

热门排行
用ASP实现网页BBS 2010-11-01
CSS cursor鼠标样式一览表 2012-06-25
.NET后台写JS代码 2011-11-03
网站地址多出jdfwkey的问题解析及... 2010-08-25
数据库xxx的日志已满,请备份该数... 2013-07-19
百度、google、Yahoo网站地图制作... 2011-01-30
<a>标签的伪类书写顺序问题... 2010-09-04
什么是长尾关键词? 2010-09-24
CEO名言 2010-08-31
Mysql 主从数据库同步 2010-09-12
博主推荐
本个人博客微信公众平台上线啦~~... 2013-10-13
饼哥网络互联上线啦~~要买域名空... 2013-09-20
网站title标题如何正确修改不会被... 2013-08-26
饼哥通讯录系统上线啦,欢迎大家... 2013-08-24
ASP .NET MYSQL 的简单分页 并不... 2013-08-19
网站有弹窗广告这样的站点,百度... 2013-08-17
做淘宝SEO优化需要注意的8大问题 2013-08-17
淘宝网怎么做SEO优化 2013-08-17
站长们要学习的“苍井空精神” 2013-08-17
苹果公司今日发布了iOS 7第五个开... 2013-08-07
随便看看
本个人博客及饼哥论坛友链广告位... 2018-08-28
11个SEO最常见问题解答 2010-08-30
描述标签到底应该怎么写? 2010-09-19
我们为什么要学习Java:Java的八... 2013-06-26
六项措施,"急救"受损Windows系统 2010-11-09
关键词密度多少比较好? 2010-09-19
标签的伪类书写顺序问题 2010-08-25
用ASP实现网页BBS 2010-11-01
js表单不能为空或全为空格 2010-09-12
电脑的140个技巧 2010-08-31
RSS新闻
传媒新闻
CSDN
八卦新闻
女性新闻
台湾新闻
互联网
军事-新浪博客
IT-新浪博客
汽车新闻
游戏新闻
国际新闻
国内新闻
体育新闻
我的微博
北京 上海 杭州 深圳 广州 成都