在服务器端保存ViewState

1.比较

Asp.net 的一个强大的功能就是ViewState,  但是这也成为很多人诟病的地方,我们先来看一个实例

ViewState其中一个特性就是保存页面的状态,下面我们看一个很简单的登录页面。

(1) 默认的页面存储

下面两幅图是使用默认的ViewState, Asp.net把状态保存在页面的一个Hidden控件里。每次请求时往返于客户端与服务器之间,我们可以看到储存了很多的值,页面大小是28.2K。

image

image

(2)自定义的Cache存储

下面两幅图是我们使用自定义的Cache存储,页面的大小是27.5K,虽然不到1K,但这个页面的结构比较简单,如果复杂的,如用了GridView等,这个差别还是比较大的

image

image

(3)扩展

实际上ASP.NET2.0 给我们提供了改变存储的功能,这个是通过覆盖Page的PageStatePersister

 protected override PageStatePersister PageStatePersister

 

而且ASP.NET2.0给内置了一个SessionPageStatePersister. 可以容易的把ViewState存到Session里

  return new SessionPageStatePersister(page);

 

2. 示例

这里我给出自定义的一个实例

(1)开发一个ViewStateFactory,根据不同的配置,修改存储方式。

using System;

using System.Collections.Generic;

using System.Web;

using System.Web.UI;

using System.Web.Caching;

namespace TestViewState

{

    public enum ViewstateMode

    {

        Cache,

        Session,

        Page,

        File,

        Database

    }

    public class ViewStateFactory

    {

        public ViewStateFactory()

        {

            //

            // TODO: Add constructor logic here

            //

        }

        public static PageStatePersister CreateViewState(ViewstateMode mode, Page page)

        {

            switch (mode)

            {

                case ViewstateMode.Cache:

                    return new CacheStatePersister(page);

 

                case ViewstateMode.Session:

                    return new SessionPageStatePersister(page);

 

                case ViewstateMode.Page:

                case ViewstateMode.File:

                case ViewstateMode.Database:

                    return new HiddenFieldPageStatePersister(page);

                default:

                    return new HiddenFieldPageStatePersister(page); 

            }

        }

    }

//实现一个自定义的方式,存储到服务器的Cache里

    public class CacheStatePersister : PageStatePersister

    {

        private Cache mCache = HttpRuntime.Cache;

        public CacheStatePersister(Page page) : base(page) { }

 

        public override void Load()

        {

            string _vskey = Page.Request.Form["_VIEWSTATE_KEY"];

            if (_vskey == null)

            {

                base.ViewState = null;

            }

            else

            {

                base.ViewState = mCache[_vskey];

            }

        }

 

        public override void Save()

        {

            string _vskey;

            _vskey = "VIEWSTATE_" + HttpContext.Current.Session.SessionID + "_" + Page.Request.RawUrl +

               "_" + System.DateTime.Now.Ticks.ToString();

 

            mCache.Add(_vskey, base.ViewState, null,

                System.DateTime.Now.AddMinutes(HttpContext.Current.Session.Timeout), Cache.NoSlidingExpiration,

                            CacheItemPriority.Default, null);

 

            this.Page.RegisterHiddenField("_VIEWSTATE_KEY", _vskey);

        }

    }

}

(2)为了可以配置,我们在Web.config的AppSetting里加上

  <!--this is for where save viewstate, correct value is Cache, Page, Session-->

  <add key="ViewStateMode" value="Cache"/>

(3)覆盖页面的PageStatePersister,这里你可以开发一个BasePage,在基类里覆盖,所有的页面集成这个页面

protected override PageStatePersister PageStatePersister

        {

            get

            {

                ViewstateMode viewstateMode = ViewstateMode.Page;

                try

                {

                    switch (ConfigManager.ViewStateMode.ToLower())

                                    {

                                        case "cache":

                                            viewstateMode = ViewstateMode.Cache;

                                            break;

                                        case "session":

                                            viewstateMode = ViewstateMode.Session;

                                            break;

                                        default:

                                            viewstateMode = ViewstateMode.Page;

                                            break;

                                    }                                   

                                    return ViewStateFactory.CreateViewState(viewstateMode, this.Page);

                }

                catch (Exception ex)

                {

                    return base.PageStatePersister;

                }

 

            }

        }

作者: 王德水
出处:http://www.cnblogs.com/cnblogsfans
版权:本文版权归作者和博客园共有,转载需经作者同意。

posted @ 2008-11-20 16:51 王德水 阅读(1955) 评论(12) 编辑 收藏

 回复 引用 查看   
#1楼 2008-11-20 17:06 高义      
放在 ViewState 中其实也是不安全的 ViewState 也可以被别人查看
 回复 引用 查看   
#2楼[楼主] 2008-11-20 17:29 王德水      
@高义
这个是存页面的一些状态,比如TextBox里的值

 回复 引用 查看   
#3楼 2008-11-20 17:49 ★金★      
ViewState感觉是鸡肋
 回复 引用 查看   
#4楼 2008-11-20 17:53 泊远      
刚看了一篇文章,讲的也是SessionPageStatePersister:开源项目大家谈-网站性能调校-Page State Persistence http://www.cnblogs.com/DotNetNuke/archive/2008/11/19/1336862.html



 回复 引用 查看   
#5楼[楼主] 2008-11-20 17:59 王德水      
@泊远
这个是一个简单的实现,那篇写的更好,补充一下

 回复 引用 查看   
#6楼[楼主] 2008-11-20 18:00 王德水      
@★金★
能避免不用viewstate当然更好

 回复 引用 查看   
#7楼 2008-11-20 20:54 canbeing      
@泊远
呵呵,我也想说这个。

觉得这个更简单易懂,那个是DNN的VB.net写的,不习惯,呵呵

 回复 引用 查看   
#8楼 2008-11-20 22:31 墙头草      
 回复 引用 查看   
#9楼 2008-11-20 23:39 Vincent Yang      
完全不明白lz什么意思,如果你用form又觉得viewstate累赘那你不如用mvc,而且msdn杂志上也有很多都写过类似文章,最后都不是最好的解决办法。
 回复 引用 查看   
#10楼 2008-11-22 11:39 小No      
你这个代码有些问题

由于每次Save时都会产生一个新的Cache,而你Load完之后没有移除上一个Cache,这样会产生很多没用的Cache,浪费资源

还有一点你没有保存ControlState

 回复 引用 查看   
#11楼[楼主] 2008-11-22 17:17 王德水      
@小No
不产生新的cache怎么保存历史呢?

 回复 引用 查看   
#12楼 2008-11-26 15:11 小No      
--引用--------------------------------------------------
王德水: @小No
不产生新的cache怎么保存历史呢?
--------------------------------------------------------

我是叫你LOAD完之后移除上一个CACHE,不是叫你不产生新的CACHE