为非回调页面保存状态
来源:互联网 发布:域名由哪几部分组成 编辑:程序博客网 时间:2024/05/23 23:50
做ASP.NET开发的人都知道,控件使用ViewState保存自身的状态,并通过回调时的表单值来控制自身的行为,例如显示数据、触发事件等。在默认情况下,ViewState是通过发送到浏览器页面中的一个隐藏域(HiddenField)来进行值的传递,因此,只有在页面回调的时候才能取到ViewState中的相应值。当然,这也是ASP.NET的基本处理方式。
但在某些应用上,这种处理方式可能会无法满足我们的需求。举例来说,一个典型查询页,上面会提供一些查询条件让用户选择,用户在输入查询条件之后找到自己想要的结果,然后点击相应的结果进入另一个页面(姑且称之为内容页吧),在这个页面中完成自己操作后,返回到查询页。一般情况下,我们所提供的返回功能往往是只一个到查询页的链接,那么进入重新进入这个页面时,之前所输入的查询条件都将会丢失,自然查询结果也就不会存在了。这时,如果用户需要先前的查询条件和结果,甚至是页码,就必须重复先前的查询操作去获取结果。
上述这种情况对于一些简单的查询来说并不是很大的问题,但对于一些数据量大、查询条件复杂的情况会非常麻烦,用户不得不多次重复做一些相同的事,给使用带来了级大的不便。要如何优化这种情况呢?一些人可能会说,返回功能不要用链接,而是用脚本在客户端调用history.back()让浏览器后退一步就可以了。不错,这是一种解决办法,但是,如果在内容页里进行了一些回调,这种简单的“后退”仍旧是不合适的。那么,要怎么样做才能满足要求呢?
先来分析一下问题,控件的状态是通过ViewState保存的,因此要还原先前用户输入的内容了,就必须在页面处理请求时加载ViewState,另外,为了完整地还原页面的状态,除了ViewState以外,还需要保存从客户端POST过来的所有表单内容。但如本文开头所说,ViewState是保存中浏览器的隐藏域里,如果不是回调就没办法取到,另外,ASP.NET也不会在非回调的情况下加载ViewState。很明显,如果要在非回调的情况下还原控件状态,有两个问题需要解决,一是要在非回调的情况下获取最后一次请求页面时ViewState和表单的内容,二是要让Page认为当前请求为回调,即Page.IsPostBack属性值为true,因为只有这样才能完整地模拟PostBack操作。
要解决第一个问题并不复杂,我们可以把ViewState和表单的内容保存在服务端内存中,可以重载Page.SavePageStateToPersistenceMedium方法将值存入服务端内存。但重载该方法并不能直接获取表单内容,但可以通过Page.DeterminePostBackMode方法取得。这样,只要把两个变量以合适的方法放入内存就可以了。我选择的办法是用一个Pair对象保存视图和表单内容,再将它们放入Session中。当然,除了Session,还可以用HttpRuntime.Cache等。如果要加载保存在服务端内存中的内容,可以重载Page.LoadPageStateToPersistenceMedium方法。
第二个问题就是要让Page认为当前是回调模式,即IsPostBack返回的值应为true。通过对System.Web源代码的分析,我发现当Page.DeterminePostBackMode方法返回的值不是空值时,就可以达到我们的目的,而这个方法又是可以重载的,这样问题就变得简单了。重载DeterminePostBackMode方法,若基类方法返回的值是空值,就从先前在Session中保存的状态取得上一次保存的表单值。其实关于DeterminePostBackMode方法,MSDN中的解释并不多,我也是从字面上猜测,结果对源码的分析得来的,是否合理还有待验证。
OK,两个主要问题都解决了,接下来就可以用代码来实现。
- Pair _state;
- /// <summary>
- /// 已重载。如果可能,从服务端内存中还原视图内容。
- /// </summary>
- /// <returns></returns>
- protected override object LoadPageStateFromPersistenceMedium()
- {
- object state;
- if (_state != null)
- state = _state.First;
- else
- state = base.LoadPageStateFromPersistenceMedium();
- return state;
- }
- /// <summary>
- /// 已重载。将当前视图内容和请求参数集合保存至服务器内存。
- /// </summary>
- /// <param name="state"></param>
- protected override void SavePageStateToPersistenceMedium(object state)
- {
- base.SavePageStateToPersistenceMedium(state);
- var ps = _state;
- if (ps == null)
- {
- ps = new Pair(state, base.DeterminePostBackMode());
- Session["page_state"] = ps;
- }
- else
- ps.First = state;
- }
- /// <summary>
- /// 已重载。当基类方法返回空值时,尝试从服务端内存中获取先前保存的请求参数集合。
- /// </summary>
- /// <returns></returns>
- protected override System.Collections.Specialized.NameValueCollection DeterminePostBackMode()
- {
- var coll = base.DeterminePostBackMode();
- if (coll == null)
- {
- _state = Session["page_state"] as Pair;
- if (_state != null)
- coll = _state.Second as System.Collections.Specialized.NameValueCollection;
- }
- return coll;
- }
以上代码的实现方法仅提供一种思路,并不是最终解决办法,因为还有许多细节的问题要考虑,并且也没有进行过广泛的应用,因此对可能造成的问题基本上是不可知的。欢迎有兴趣的人一起讨论。
- 为非回调页面保存状态
- silverlight页面保存为PDF
- silverlight页面保存为图片
- html保存页面为图片
- .Net保存页面滚动条状态
- Activity页面状态保存 持久化
- Android Fragment 保存页面信息以及状态
- 巧用location.hash保存页面状态
- JavaScript利用Cookie保存页面状态信息
- 用闭包保存状态的实例 - 为页面上所有的a元素添加handler点击时alert index
- 页面无限跳转间如何保存页面状态(1)
- 页面无限跳转间如何保存页面状态(2)
- 页面无限跳转间如何保存页面状态 (3)
- 页面无限跳转间如何保存页面状态
- 页面无限跳转间如何保存页面状态
- 页面无限跳转间如何保存页面状态(1)
- 页面无限跳转间如何保存页面状态(2)
- 保存页面为MHT的代码
- 我唉博客
- div相对定位和div绝对定位
- DOS下面关于精确延时1ms的函数(理论上可以非常精确延时到10微妙级别)
- HTML-鼠标经过图片放大收藏
- 下拉菜单中的数据跟数据库中的数据进行索引匹配
- 为非回调页面保存状态
- vmware linux访问windowsxp下的文件
- 转载vs最常用的快捷键(转载)
- Pocket PC与Web Service连接访问数据库
- 传说中的100句英语可以帮你背7000单词
- 每个JAVA初学者都应该搞懂的6个问题
- ★ 索引应用案例——oracle
- sql中exist与in的区别
- 最易被商家“掺毒”的十五种食品