回发或回调参数无效和省市级联的问题

用.net在web开发中我们有时候会用到省市无刷新级联,既然要无刷新就要用到Javascript,大多数人选择控件的时候也会用DropDownList,或许你绞尽脑汁终于把无刷新级联做出来了,但是在后台取DropDownList的值的时候你会惊讶的发现,报黄页了!太痛苦了,想了好久终于写出来的无刷新级联就这样被微软处于安全原因而抛出错误!(我用的是framework3.5和VS2008)。好了,既已引入了话题,我们下面具体的看一下这个错误和对于这个错误的解决方案。

 

错误描述:

回发或回调参数无效。在配置中使用 <pages enableEventValidation="true"/> 或在页面中使用 <%@ Page EnableEventValidation="true" %> 启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用 ClientScriptManager.RegisterForEventValidation 方法来注册回发或回调数据以进行验证。

 

页面错误截图:

 123

 

错误出现的地方:

做好省市级联后(默认用的是DropDownList),取省市的SelectedValue时候。

 

解决方案:(这是我自己想的,如果你有更好的可以忽略)

在网上搜了一下,好多好多文章对于这个问题介绍的都是以下三个个原因:

一是Form嵌套,一个页面只能有一个Form,仔细检查代码就可以解决。

二是在下拉菜单中使用ajax,常见于省市联动菜单,可能是由于在aspx页面赋给了下拉菜单初始Item值,在事件回发时提示该错误,将下拉菜单初始Item值删除,在绑定事件中添加Item项。

三是在给DropDownList赋value值的时候有中文。

找到的解决方案也都大同小异:

第一,   在页面头部或者config文件中配置EnableEventValidation="false";

第二,   在web.config中添加如下语句:<globalization requestEncoding="utf-8" responseEncoding="utf-8" culture="zh-CN" uiCulture="zh-CN"/>

这两个方法我都试了,都不行,要么与本意:做省市无刷新级联冲突要么没效果。想来想去,我感觉下面的做法是比较好的:

首先,我们要做无刷新级联,必须设置EnableEventValidation="false",设置后会出现一个问题:在后台用SelectedValue获取DropDownList的值的时候永远都是0!无论你换什么方法获取value值,都是0!

然后,我们可以用一个隐藏的html标签代替用SelectedValue取值:

<input type="hidden" id="input_CityID" runat="server" />

  在写这个标签的时候,把它写成runat="server",这样在后台就可以直接获取该隐藏控件的值。在页面写如下的JS代码:

var City=document.getElementById("<%=ddl_City.ClientID %>");

var CityID = City.options[City.selectedIndex].value;

 document.getElementById("<%=input_CityID.ClientID %>").value=CityID;

如此一来,就可以既用无刷新省市级联又可以获取ddl的值。

 

 

enableEventValidation是跟ASP.net中的EVENTVALIDATION有关,具体如下,以下为非原创,原文连接为:http://hi.baidu.com/carsonguo/item/f9d2541bed3323623f87ce29

 

ASP.net 添加了"event validation"的功能, ASP.NET会检查 POST方法中的所带的参数,如果
认为不合法,就会抛出异常,信息如下

     Invalid postback or callback argument. 
         Event validation is enabled using <pages enableEventValidation="true"/> in 
     configuration or <%@ Page EnableEventValidation="true" %> in a page.  
         For security purposes, this feature verifies that arguments to postback or 
     callback events originate from the server control that originally rendered them.  
         If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation 
     method in order to register the postback or callback data for validation. 
    
这个设计的目的是为了防止恶意用户利用post 方法发送一些恶意数据.但是有时一些常见的
case也会出错,比如使用客户端脚本,根据页面上的其他控件的内容来改变一个dropdown list的内容,最常见的case
就是省市县3级联动菜单.又比如在页面上添加一个dropdown list,然后给它添加3个item,再使用客户端脚本在
dropdown list中添加一个item,如果dropdown list的AutoPostBack="True",每次选择list item都会引起postback, 
如果所选的item为dropdown list本来就有的,一切正常.如果所选的item是通过客户端脚本添加的,就会出现异常.

在asp.net render DropDownList 时,会遍历DropDownList的item,并记录所有可能的postback的值,其算法为
hash(DropDownList’s UniqueID XOR hash(ListItem’s Value property)),计算的结果会被保存在page中,

<input type="hidden" 
        name="__EVENTVALIDATION
        id="__EVENTVALIDATION"
        value="/wEWBQKGg9abDQKd9sHMBgKc9s…….." 
/> 
这个过程发生在control的Render()方法中
当页面postback时,ASP.NET会根据这个隐藏值检查postback values,如果找不到对应信息,就会报错

结局方案
1. 禁止这个功能, 但同时会失去一些安全保障:
//—-通过web.config
<system.web>
    <pages enableEventValidation="false"/>
</system.web>
//—-针对某个page
<%@ Page EnableEventValidation="false" … %>

2.Register For Event Validation
其原理就是让asp.net记录这个postback value.
RegisterForEventValidation必须在render时调用.

protected override void Render(HtmlTextWriter writer)
{
    ClientScript.RegisterForEventValidation(_recipeList.UniqueID,"4");
    base.Render(writer);
}

如果我们自己写了一个control,需要使用validate

posted @ 2013-07-16 12:23  追你追到  阅读(273)  评论(0编辑  收藏  举报