大家都听说过也用过ASP.NET中的ViewState本质,到底ViewState本质上到底是什么东西?为什么ASP.NET中没有他不行?下面就来谈谈。。。
我们一般在开发面向对象程序的时候,我们都是用对象保存数据的,比如用对象的属性,字段来保存对象的状态。当调用对象的方法时,就可以改变对象的状态。释放对象后,对象的状态就消失。这点大家都熟悉。在开发桌面程序的时候,没有什么问题,因为对象都一般在本地的内存中,直到不再用那个对象,我们就销毁它。
但是在Web程序中,问题就大了,比如我们请求一个页面的时候,我们希望把上一个页面的状态保存下来,因为下一个页面要用到上一个页面的状态,常见的例子就是填写用户信息时,我们要把这次的信息和上一个页面中的信息的比较,如果信息不同,就进行一定的操作,等等。但是一旦页面交给服务器后,上次的页面的状态信息就丢失了(HTTP协议是无状态的)。
所以ASP.NET视图机制就可以在请求结束时保存对象的状态,同时在下一个对象请求开始时加载之前的状态,下一个请求按照下面的步骤来加载状态:
1.创建一个与上一个请求结束时所注销对象相同类型的新对象。比如,我们第一次请求的是Default.aspx页面,在服务器端,ASP.NET运行时就会编译Default.aspx页面,经过一系列的动作之后,在服务器端就有一个Default_aspx类的实例,然后再经过一系列的动作之后,就把我们请求的Default.aspx页面的数据最后以html的形式发送了到我们的浏览器中。
此时服务器的Default_aspx的实例就销毁了,对象就没有了。当我们再浏览器中填写了相关的信息后,再次请求提交Default.aspx页面时,服务器又会重新编译Default.aspx 页面,在然后经过一系列的动作后处理我们的数据。再次把处理的结果发送给我们,然后Default_Aspx实例再次销毁了。
假如我们第三次还是请求的Default.aspx页面,我们把数据再次提交,然而这次Default__aspx的实例就只是处理我们这次提交的数据,不会管我们之前提交的数据。说的更加的通俗就是,我们第二次提交的数据是A,我们第三次提交的数据是B,而且我们本次希望页面把A和B数据比较之后再发送 C数据给我们的,但是本次的处理页面只是直到本次的提交的数据,即B。所以我们永远得不到C的结果。
2.为新建的对象加载旧对象的状态。
只有这样我们才可以得到我们想要的数据C。我们来进一步看看内部机制。在每个请求结束时(简单的就可以认为在服务器把数据发送给我们之前,此时数据还在服务器),就会引发一些事件,调用一些方法:
◆页面自动调用Controls集合中控件的SaveViewState方法,也就是迭代页面中所有控件,调用他们的SaveViewState方法,因为控件都是Control的子类,而Control类中有这个方法。
◆每个控件的SaveViewState方法把控件的状态存储到一个对象中。
◆页面获取每个控件的返回的那个保存状态的对象,然后用与对象有关的转换器把保存的状态的对象转换为字符串,然后把这些字符串表达式组合起来保存在一个隐藏字段中,隐藏字段名为:_VIEWSTATE.如下:
- <input type=”hidden” name=”__VIEWSTATE” id=”__VIEWSTATE” value=”/wEPDwULLTE3MDU5MjY
- 4MTkPZBYCAgMPZBYCAgEPFCsAAmRkFgZmD2QWAmYPDxYCHgRUZXh0BQ5QYXltZW50IE1ldGhvZGRkAgEPZB
- YCZg8PDxYCHgtfIURhdGFCb3VuZGdkZGQCBw9kFgRmDw8PFgIfAWdkZGQCAg8PDxYCHwFnZGRkZJDAqbyjC
- j4rjagRWSiVYTp7nQfM” />
◆然后_VIEWSTATE隐藏字段就发送到了客户端,和页面数据一起。
◆当页面回传到服务器,就发生下面的操作:
页面字符串从_VIEWSTATE中得到字符串表达式。
页面矿建解析字符串表达式
页面框架使用与对象相关的类型转换器,根据字符串表达式重新创建状态对象。
页面框架调用Controls集合中每个对象的LoadViewState方法加载之前的状态
然后进行其他的处理。
就这样,ASP.NET就在请求之间保存了状态。
总结:以上就是ViewState本质介绍,大家可以这么认为:服务器端把页面中对象的状态序列化到客户端,然后下面再反序列化得到之前的状态。
【编辑推荐】