代码改变世界

如何驾驭ViewState利剑

2010-02-05 15:35  邢少  阅读(2919)  评论(11编辑  收藏

       ViewState状态视图是asp.net Webform 模型的一个非常重要的概念,它是保持web窗体状态基于浏览器的方法,主要的功能就是保持Web控件的持久性。在刚刚接触.net web编程的时候,感觉Web编程和Winform的编程好像没有什么不一样,只是一个IsPostBack的概念比较头疼,那时候对状态视图还真是不知道,感觉Webform是理所当然的。随着时间的过去,接触web开发已经有2年的时间,已经知道了ViewState 的存在,以及它在使用中的一些使用技巧。 现在自己总结一下,希望各位兄弟可以指正,并交流ViewState的使用。

       ViewState是一种机制,asp.net用它来保存服务端控件的状态值。如果您是个经验丰富的.NET 开发人员,一提起 ViewState ,绝对会有非常恶心的感觉,因为你第一个想到的是大量通过“鸡尾酒吸管”吸入的 Base64 编码数据,那些编码数据存储在页面的一个id为 “_VIEWSTATE” 的隐藏字段中 <input>。这样在回传的时候,服务端首先对隐藏字段中的编码进行解码,并得到回传前的状态值进行操作,操作完成后,再次编码写入页面_ VIEWSTATE字段,并发送到客户端。这样在开发过程中就可以专注与业务逻辑,不要管页面状态的问题。但是同样它的这种机制虽然很方便,使web编程更加的简单,但是编码数据实在是让人恐惧,在进行一些状态操作比较复杂的功能的时候,它生成的隐藏字段的编码的长度是很恐怖的,

       我曾经有过惨痛的经历,在最初写web程序的时候写过一个页面的体积在运行后查看页面大小,竟然达到了300多K,而光隐藏字段就200多k,一看网页的源码,望不到边的字符编码,最后经过分析找到原因:因为我在状态视图里面存储了而一个类。为什么要存储呢,是因为我在页面逻辑中增加了一个在winform中常用的功能,在页面进行虚拟表的增删改查,在提交触发的时候,一起提交虚拟表。结果可想而知,当时很无奈,不知道怎么处理这个问题,后来是通过把table存在了Cache中解决了问题,这个是比较明显的问题。在实际的开发过程中,每个aspx页面都或多或少的存在这些状态视图编码。Web程序的加载速度是衡量程序性能的一个关键标准,网络传输量是加载速度的根本。所以,人们都说优化web程序的60%的工作量是减少网络传输量。

       搜寻过网络上的资料,在优化ViewState上有不少的文章,但是都无外呼是三种方式:

       1、压缩ViewState体积;

       2、减少不必要的ViewState;

       3、将ViewState视图编码存储在非页面介质中;

       首先说一下第二种,减少不必要的ViewState编码,对不需要记录控件状态的页面一定要记住将EnableViewState置成“false”,这样页面在生成的时候,就不会记录控件的状态,那么页面就少了Viewstate的编码,减少了页面的大小。对没有设及状态操作的控件或者页面一定要禁用viewstate。举个例子    比如在新增页面、如果你的页面有大量的文本框等其他控件,这时候在请求的页面中,你可以通过查看源代码看到大量的状态编码。真实的新增操作:只要填入信息à点击保存à提交到服务端存储à过程结束。页面捎带者那些编码,完全是没有必要的性能损失。如果你页面的控件很多的话,那些编码的体积是很可观的。我实际测试、一个人员信息新增页面的 页面体积是 99k,其中状态视图编码就有 28k,性能可能高吗?所有这种不必要一定去掉。还有就是数据显示的时候,gridview 或者repeater 在绑定出数据列表的时候,状态视图编码是体积大的一个主要问题,它在ViewState中存储了数据的状态,还有就是绑定事件的状态。如果页面数据只是显示的话,你完全没有必要打开它,直接EnableViewState=”false”就可以了,但是如果你的数据绑定了事件,还是不要禁用了,不然你的事件就会失效了,因为你的绑定事件状态是记录在ViewState中的。所以在web开发中,对EnableViewState属性还是时时考虑吧,因为它真的很重要,起码对高性能程序很重要。

       说到第一(压缩ViewState体积)种方式,它通过对PageStatePersister 的重写来实现的优化。压缩ViewState体积是用一些压缩方法,对状态视图编码进行压缩,也就是在.Net原有视图状态编码的基础上,再一次压缩。在使用状态视图的时候,再解压缩出来使用就可以,虽然有了一定的性能损耗,但是相比较它在网络中传输来说。感觉还是有了提高的,页面小了吗,最大的压缩比应该能到40%左右吧,主要看压缩的方法了。页面加载大部分的时间是页面传输的时间,所以这个方式在一定情况下还是可用的。具体的方法就在以后的文章中再写详细的实例吧,在这就不多说了。

       最后说一下ViewState存储到非页面介质这种方式,它和第一种一样,都是通过重写

PageStatePersister来实现非规则的操作。.net是在编码状态后,将编码写入页面的隐藏字段,现在呢,用一种别的方式存储,把它们写入 session、cache、文件、数据库等。这样就从页面彻底抹去这个隐藏字段,只要编写一个新的PageStatePersister,在使用页面override就ok了,这种情况是典型的空间换时间。在硬件性能可以承受的基础上,效果还是很明显的。

       最后,没有绝对的性能高低,因为性能是一个综合性的问题,软件只是一个方面而已。硬件、网络条件都是重要的因素,但是作为一个程序员或者开发者,只要实事求是的掌握平衡就能掌握性能。在以后的文章中会总结具体的viewstate优化方式,主要是针对压缩ViewState体积和将ViewState视图编码存储在非页面介质中。

       纯属个人意见、有异议的可以多交流,互相进步吧。