错误信息:The client disconnected. 2009-4-6 19:35:41
at System.Web.UI.ViewStateException.ThrowError(Exception inner, String persistedState, String errorPageMessage, Boolean macValidationError)
at System.Web.UI.HiddenFieldPageStatePersister.Load()
at System.Web.UI.Page.LoadPageStateFromPersistenceMedium()
at SpringStudio.Naming.Website.PageBase.LoadPageStateFromPersistenceMedium()
at System.Web.UI.Page.LoadAllState()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
看看StackTrace就知道,这个错误是由于ViewState引发的。ViewState是个让人即爱又恨的东西。说是爱吧,是因为用起来很方便,控件的状态能自动维持。说是恨吧,原因是其性能不是太高,尤其是页面较大的时候。不知道当初微软在设计.NET的时候为什么的引入ViewState机制,我研究过一些用.NET开发的网站,很多网站都是直接禁用了ViewState。原因很简单,一个稍微大一点的页面,产生的ViewState简直让人受不了,这么大的ViewState将对网络带宽带来极大的压力。同时,对系统性能也会造成一定的影响,因为为了能把数据存储在网页中,系统必须对各种对象做串行化处理,最后编码为Base64的字符串存储在网页中的隐藏字段中(一般默认是存储在名为__VIEWSTATE的隐藏Field中)。当网页被Post到服务器的时候,服务器又将对里面的数据做反串行化处理,在反串行化之前还得验证数据的完整性和正确性。上面这个错误,就是因为在反串行化的过程中,由于客户端浏览器未能完整的Post保存在ViewState中的数据而引发的异常。如果用户所在的网络情况不是很好,Post一个表单需要较长的时间,用户在等待的时候点击了“停止”按钮,或者干脆转向了其他页面,这个时候,客服端单方面中断了网络链接,即所谓的“The client disconnected”,导致回发的ViewState不完整而引发了此异常。一般情况下,这个异常对于服务器和用户体验都不会带来太大的影响,故服务器在捕获到这个异常的时候可以忽略它。
即便我们可以忽略这个异常,但有几点还是值得注意和思考:
1. 页面中不需要的ViewState的控件,尽量将其EnableViewState设置为False,这样可以大大降低网页的ViewState。如果你的页面更本不需要使用ViewState,则干脆从页面级,甚至是整个站点级(在Web.config中设置)禁止ViewState,这样就能有效防止该异常的发生,同时提高系统性能。
2. ViewState从设计上来说是个好东西,但苦于网站的带宽和服务器资源总是有限的,所以在设计网站的时候,就得尽量少用ViewState。等什么时候,我们的网络带宽足够大,并且Server足够Powerful的时候,这个问题就可以忽略了。
3. 如果非要使用ViewState,有两种方法可以减少ViewState的大小。第一,启用压缩技术。在ViewState被发送到客户端之前,调用压缩算法将其压缩。根据我的经验,就是一般的zip压缩,压缩率也在30-50%之间,有的甚至更高,这取决于具体的数据。当数据回发的时候,先将其做解压缩处理,然后在执行其他的ViewState操作。第二,将ViewState存储在服务器的硬盘上面,道理一样,在发送到客户端之前,将数据以文件的形式保存在服务器的硬盘上。这里需要注意的是文件名必须的唯一,原因就不多说了。当页面回发的时候,直接根据文件名从硬盘上加载ViewState即可。这两种方式的实现都很简单,重写页面的如下两个事件即可:
- protected override void SavePageStateToPersistenceMedium(object viewState)
- {
- // 压缩ViewState或者存到到硬盘上
- }
- protected override object LoadPageStateFromPersistenceMedium()
- {
- // 解压ViewState或者从硬盘加载数据
- }
4. 如果本身网页的ViewState不是很大,网站却经常抛出这个异常,则至少可以说明你的网站速度太慢了,用户在提交表单的时候需要花费一个较长的等待时间。这种情况,就得考虑为你的网站做带宽和硬件上的升级了。