当ASP.NET发生Viewstate MAC的验证失败(machineKey)

问题是这样的,当 ASP.NET 因为网页还没全部下载完成时,使用者就按下网页中的任意一个PostBack 的按钮或链接时,就会发生「Viewstate MAC 的验证失败」的错误讯息!

这问题实在很难除错(DEBUG),我想很多人连发生的原因都不知道,主要的发生原因有两种:

1. 当网站采用 Web-farm 架构时,也就是一个网站采用负载平衡的架构,用多台 Web 主机同时提供服务时。

因为 ASP.NET 预设会将 Viewstate 编码加密,验证数据的加密类型是 SHA1,验证加密数据的密钥(Key)预设是「自动产生」,所以每一台Web主机所产生的Key都不一样,所以你采用多台主机同时提供服务时,就可能会遇到从第一台Web主机读到的内容,做 PostBack 时可能会 PostBack 到第二台主机,但第二台主机看不懂第一台主机编码过的 Viewstate,而导致「Viewstate MAC 的验证失败」的例外发生!

这时你需要统一每一台主机的 machineKey 才能让每一台的编码加密的内容可以被正确验证!建议您去 The Code Project 网站看这份文件:ASP.NET machineKey Generator 上面有完整说明!

2. 因为网页还没全部下载完成,导致页面的状态不完整时就对服务器发出 PostBack 要求,因为 ViewState 不完整,而导致 Viewstate 验证失败。

这个问题只能将修改网站的 web.config 设定将 Viewstate 全部关闭才不会发生错误!如下:

<pages enableEventValidation="false" viewStateEncryptionMode ="Never" enableViewStateMac="false"/>

ASP.NET ViewState初探

话说在新公司上班快2周了,这里的工作和业务还是有些意思和挑战的。这几天1直在重构公司之前的一个项目,出于保密协议这里不能提项目名称,作为对新人的关爱,我仅负责其中1个模块的1个页面,这个页面的性能有些问题,当大批量进行数据修改的时候,提交和响应会非常的慢,我需要做的是就是改善它的性能。

花了一天时间分析了这个页面的有关代码,实在很头痛,大量的服务端控件、大量的事件、大量的重复代码,发现问题的关键在于该页大量的服务端控件(GridView嵌套大量DropDownList、TextBox、CheckBox)及大量的迭代查询。

于是狠心下来进行重构,越深入发现问题越多,根本无法重构,除非整个模块和某些底层推倒重来,但是工时将纠人心窝(明早开会把情况说明PM估计要跳的了)。

这个项目通过微软传统的WebForm Code Behind编程模型,大量使用事件和服务端控件,说到服务端控件,有个很重要的属性EnableViewState,它保持着页面回转的状态,借这次Code Review的机会,将Asp.Net ViewState进行一次复习。

ASP.NET ViewState 初探


ViewState 到底是什么

与刚接触 ASP.NET 页面的开发人员交谈时,他们通常向我提出的第一个问题就是:“那个 ViewState 到底是什么?”他们的语气中流露出的那种感觉,就象我来到一家异国情调的餐馆,侍者端上一道我从未见过的菜肴时的那种感觉 —— 既疑惑不解,又充满好奇。但肯定有人认为它不错,否则就不会提供了。所以,我会先尝一尝,或许会喜欢上它,尽管它看上去的确很古怪!
对于 ViewState 也是如此,但是如果适应了它的风格,您会发现在许多情况下,您将乐于在自己的 ASP.NET 应用程序中使用 ViewState,因为它可以帮助您使用更少的代码完成更多的工作。但是,有时也会对 ViewState 完全弃之不用。下面我们就这两种情况分别进行阐述,不过,让我们先回答什么是 ViewState 这个问题。
答案:ViewState 用于维护页面的 UI 状态
Web 是没有状态的,ASP.NET 页面也没有状态,它们在到服务器的每个往返过程中被实例化、执行、呈现和处理。作为 Web 开发人员,您可以使用众所周知的技术(如以会话状态将状态存储在服务器上,或将页面回传到自身)来添加状态。下面我们以图 1 中的注册窗体为例进行论述。

Continue reading “ASP.NET ViewState初探”