“视图状态损坏”的困扰

如果你在调试或访问ASP.NET页面的时候遇到“此页的状态信息无效,可能已损坏”的异常,我相信你会束手无策的。因为网上能搜到的解决方案和微软的KB831150,都只会让你更迷惑。当然,我这里也不是给出解决方法,而是记录下我是如何遇到这个问题和如何避开这个问题的,希望对你处于类似场景中时能有所帮助。

一、问题回显

出问题的页面是一个注册页面。里面用到很多验证控件、输入框、下拉框,其中包含多个自定义验证控件,客户端的验证方法同时用到了jQuery。

出问题的症状是:当用户填写了用户名,点击了“检查用户名是否可用”,结果显示在一个id为accountHolder的span里,然后填完其他项,点击注册按钮,就出现错误页面了。

黄色经典错误页面如下:

一句“没有相关源行”将我们狠狠推开,无从调试。

通过各种途径(包括删掉控件、删掉验证、禁用脚本等等方法,花了一天多时间哦。结果在这里一句话就叙述完了,太不甘了)最后将视线定位在了一个用ajax实现的校验重复用户名的javascript方法上。这个javascript方法代码如下:

Code
function checkAccountExists(){
var name = $("#nameBox").val();

if (validateName(name)){
$.ajax({
type:
"POST",
url:
"handlers/account
.ashx",
cache:
false,
data:
"name=" + name,
success:
function(data){
$(
"#accountHolder").html(data);
},
error:
function(data){
$(
"#accountHolder").html("系统异常,未能核对帐户名。");
}
});
}
else{
$(
"#accountHolder").html("");
}
}

 

其中validateName(name)是一个正则测试方法。

由于这个错误难以调试,现在就寄希望于HttpWath能给我们一些提示了。

二、HTTP请求和响应信息

用HttpWath可以跟踪请求,来看一个出现错误后的截图吧:

ajax请求的地址是CheckAccountExists.aspx,这个页面用Response.Write返回校验的结果,我以为是POST的问题,把方法改成了GET(点击看大图):

无论POST还是GET获取校验结果,都返回500,也就是都返回黄色页面。到这里我已经很着急了,无论怎么调整控件和禁用脚本,它依然出错。

后来把ajax的请求换了一种方式处理,换成了一个Handler(实现IHttpHandler)来处理用户名校验,居然没有出错了。可以看看监测到的请求响应流:

上面是POST获取,下面是GET方式(点击看大图):

由于每次测试的时候我都清空了浏览器Cache和输入的相同数据,保证每次POST back的数据相同,你可以从上面的截图里看出来,用aspx作为ajax响应端的时候发送的数据是2058b,而用Handler的时候是1987b。这多出来的一部分是哪里来的呢?

三、结论

可能你已经发现了,可是我却经过了千辛万苦才发现啊。

从前两张HTTPWatch的截图看出,在用aspx页面当后台ajax响应的时候,不仅仅请求了aspx页面,还有两个css文件,这是因为aspx页面里有HTML代码,把css文件包含了进来,而且HTML代码里还有一个服务器端的form,问题就在这里!

用一般处理程序就不会存在这样的问题。因为它返回的东西必须由你来完成,因而也有了全部的控制权。

当然你也可以用aspx来作为ajax的后台处理程序,那么请把aspx页面的所有HTML代码删除掉,只保留@Page声明这一行即可,结果是:

谜题终于解开了。

结论是,修改别人的程序真的是很恼火的一件事,更恼火的是别人的程序还写得不好。合作的烦恼也因此而生。

另外关于排错,有的时候要到最后才能发现错误的根源,这也是相当郁闷的一件事。我之前就很不喜欢ASP.NET的Post back机制,原因之一是因为ViewState等控件在页面上太影响美观了。

四、参考资源

关于视图状态,或许你要参考如下地址:

ASP.NET 视图状态概述

TRULY Understanding ViewState

微软中文技术论坛(MSDN and TechNet)

posted @ 2008-09-28 14:35  亮小猪  阅读(485)  评论(0编辑  收藏  举报