Invalid postback or callback argument.

本文探讨了ASP.NET中EventValidation机制的工作原理及常见异常处理方法,提供了禁用验证、注册验证及绑定控件时避免异常的具体策略。

 

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 events功能,就需要使用SupportsEventValidation attribute,

[SupportsEventValidation]
public class DynamicDropDownList : DropDownList
{
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
     Page.ClientScript.RegisterForEventValidation(this.UniqueID, "4");
     base.Render(writer);
}
}

目前,asp.net还不能单独禁止某个control的validate events功能.

]]> http://kedach.blog.sohu.com/43913108.html http://kedach.blog.sohu.com/43913108.html#comment fengzoo的blog Sat, 28 Apr 2007 18:56:07 +0800 心得经验。。。 http://kedach.blog.sohu.com/43913108.html 事例:从产品表中读取数据,绑定到repeater中,并将相关数据赋值给repeater中的相关控件.

 

遇到问题:数据库中存在字段:sort (int类型) 值[1商务系列";2休闲系列;3运动系列;4牛仔系列;](即读取的是数字),但是,客户要求显示时,却要现实汉字种类.

实现:在后台代码中添加一个public方法,该方法实现将相应的数字转化为汉字,方法如下:

    public string GetState(string i)
    {
        if (i == "1")
            return "商务系列";
        if (i == "2")
            return "休闲系列";
        if (i == "3")
            return "运动系列";
        if (i == "4")
            return "牛仔系列";
        else
            return "其他";
    }

然后在前台aspx中调用该方法:

<td><%# GetState(DataBinder.Eval(Container.DataItem, "sort").ToString())%> </td>

ok,功能实现!!!!

自己鼓励一下自己,呵呵!!!

]]> http://kedach.blog.sohu.com/43686197.html http://kedach.blog.sohu.com/43686197.html#comment fengzoo的blog Thu, 26 Apr 2007 23:19:27 +0800 .NET技术及相关 http://kedach.blog.sohu.com/43686197.html 1 先在Repeater中写一个OnItemCommand
   <asp:Repeater ID="Repeater" runat="server" OnItemCommand="op_ItemCommand" >
2 再在删除那个按钮写一个CommandName
<asp:LinkButton runat="server" ID="zssc" ToolTip="删除发布页面" CommandName ="Del" OnClientClick="return confirm('确定要删除新闻的发布页面?')"></asp:LinkButton>
3 CS代码中写下面的东东

 

只用把ID绑定在一个隐藏的LABLE上面就可以了,或者你就绑定在一个Lable上面,显示给用户看到他的ID,然后在第3步“//操作代码”那个地方,你写上这么一句:

Lable lb_Repeater_ID = (Label)e.Item.FindControl("lb_ID");

解释:lb_Repeater_ID是让你在下面删除这个记录的时候用的,而后面那个lb_ID是前面页面上,你所点击的那行的控件的名字,那么你要删除的时候,就可以使用lb_Repeater_ID了,见下面:
SqlCommand cmd = new SqlCommand("delete from Table1 where id = '"+ lb_Repeater_ID.Text + "'", conn);


protected void op_ItemCommand(object sender, RepeaterCommandEventArgs e)
    {      
        switch (e.CommandName)
        {           
            case "Del":
                //操作的代码!
                break;
         }
    }

]]> http://kedach.blog.sohu.com/43685992.html http://kedach.blog.sohu.com/43685992.html#comment fengzoo的blog Tue, 1 May 2007 19:58:28 +0800 .NET技术及相关 http://kedach.blog.sohu.com/43685992.html 我们在用vs2005做数据绑定的时候运行出来的

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


有人说改成 pages enableEventValidation="false",但这样我们绑定的控件就用不了了。
我在网上查了一下,只要我们把绑定代码写在IsPostBack里就好了。
因为如果不家判断,我们在点击绑定控件时数据绑定会重做,这样我们原来绑定的东西就不存在了,在回调时就会出错.
]]> http://kedach.blog.sohu.com/43444816.html http://kedach.blog.sohu.com/43444816.html#comment fengzoo的blog Wed, 25 Apr 2007 09:45:16 +0800 IT精华文章及感想 http://kedach.blog.sohu.com/43444816.html
补充:
ASP.NET中有Event Validation(事件验证)的机制,该机制出于安全性考虑,对回送或回调的控件事件进行验证,以确保该事件由原始控件激发,并阻止可能的通过POST方法传递的恶意数据。在实践当中,有时会因为自己的不慎而引发该异常,下面以一个简单的案例说明其原理和解决方法。Sample.aspx<asp:GridView ID="GridView1" runat="server">
    <Columns>
        <aspemplateField>
            <ItemTemplate>
                <asp:Button runat="server" Text="Button" />
            </ItemTemplate>
        </aspemplateField>
    </Columns>
</asp:GridView>Sample.aspx.cspublic partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        GridView1.DataSource = Enumerable.Range(0, 5);
        GridView1.DataBind();
    }
}在用户单击GridView1中按钮的时候将会引发上述异常,原因是:(1)点击该按钮前GridView1已经绑定了数据,且Sample.aspx中隐藏字段__EVENTVALIDATION记录了GridView1及其子控件的某种哈希值,以供事件验证机制分析安全性;(2)点击该按钮激发页面回送,这将再次执行Page_Load;(3)Page_Load的再次执行使得GridView1被重新绑定,Sample.aspx页面中__EVENTVALIDATION的值被重新计算,且计算结果与(1)中的值不同,因此ASP.NET的事件验证机制认为用户POST了不安全的数据,继而触发上述异常。(4)事实上,上述逻辑并非POST了不安全数据,而是重复绑定导致__EVENTVALIDATION在点击GridView1中按钮的前后不同而已。解决方法很简单,既然是因为重复绑定导致的,且该异常与Postback有关,因此可修改Code behind为:Sample.aspx.cspublic partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
          GridView1.DataSource = Enumerable.Range(0, 5);
          GridView1.DataBind();
        }
    }
}保证了__EVENTVALIDATION前后一致,也就不会遇到那个异常了。网上还有朋友遇到了这个异常,有的是因为出现了上例那样的问题,有的是因为使用Ajax出现问题,无论那种原理都是一样的。网上盛传的两种解决这个问题的方法也顺便列在这里,在某些情况下可以解决问题,但并非每次都管用,比如对于上例就不管用了,因此必须分析导致__EVENTVALIDATION不同的原因才好修复。(1)将页面Page指令的EnableEventValidation设为false,即<%@ Page EnableEventValidation="false" … %>或为web.config添加<system.web>
  <pages enableEventValidation="false"/>
</system.web>这种方法可以暂时屏蔽该异常,但是损失了安全性,且会导致一些控件的事件的响应失灵,因此应当慎用。(2)重写页面的Render方法,并为特定的控件注册事件验证protected override void Render(HtmlTextWriter writer)
{
  Button btn = GridView1.FindControl("Button") as Button;
  this.Page.ClientScript.RegisterForEventValidation(btn.UniqueID);
  base.Render(writer);
}这种方法比(1)好些,但并非每次都能起作用

最近才学习dotNET Framework 2.0的东西,往DataList控件的<ItemTemplate>添加一个<asp:Button />,运行点击按钮出现以下异常

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

用LinkButton就不会出现这样的情况,我尝试在网上找解决办法,不过还是未能让人满意,大多都是把EnableEventValidation="false",但设置成false会让Button无反应,而且还没有局部的EventValidation,所以把EnableEventValidation设置成false不是首选解决办法。

凭我有限而且不专业的知识和不准确的理解,异常的出现都是“出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件”这句话所描述的原因,所以我觉得,只要给这些“不明”的Button给予“身份”,大概就能解决这个问题了

举个例子吧,有如下一个DataList

< asp:DataList ID = " DataList1 "  runat = " server "  OnItemDataBound = " DataList1_ItemDataBound "
                OnItemCommand
= " DataList1_ItemCommand " >
                
< ItemTemplate >
                    
< asp:Button ID = " Button1 "  runat = " server "  Text = ' <%# Eval("CompanyName") %> '  OnClick = " Button1_Click "  CommandName = " test "   />
                
</ ItemTemplate >
</ asp:DataList >

通过在Datalist对数据进行DataBind的时期对各Item的Button控件进行PostBackOptions的设置(就是给予这些Button“身份”),例子如下:

protected   void  DataList1_ItemDataBound( object  sender, DataListItemEventArgs e)
    {
        
if  (e.Item.ItemType  ==  ListItemType.Item  ||
             e.Item.ItemType 
==  ListItemType.AlternatingItem)
        {
            PostBackOptions pbo 
=   new  PostBackOptions(e.Item.FindControl( " Button1 " ));
            pbo.ActionUrl 
=   " dl.aspx?page= " + e.Item.ItemIndex.ToString();   //  回发的目标 URL
            pbo.PerformValidation  =   true ;   //  指示在回发事件发生之前是否需要在客户端进行验证
            pbo.AutoPostBack  =   false ;
            pbo.RequiresJavaScriptProtocol 
=   true ;   //  指示是否为客户端脚本生成了 javascript: 前缀
            ((Button)e.Item.FindControl( " Button1 " )).PostBackUrl  =  Page.ClientScript.GetPostBackEventReference(pbo);    // 给予Button“身份”
        }
    }
 
用上面的方法都不影响Button的Click事件和DataList的ItemCommand事件。由于个人的不专业和知识的不牢固,如有错漏请及时指出,就算是被破口大骂我也乐意接受,你们的挑剔就是我的成功之母

&lt;think> 我们正在处理一个ASP.NET中的事件验证错误。错误信息指出:回发或回调参数无效,并且事件验证被启用。 事件验证是ASP.NET的一项安全功能,用于确保回发或回调事件的参数来源于最初呈现这些事件的服务器控件。 当出现此错误时,通常是因为客户端发送了服务器不期望的参数(可能是视图状态被篡改,或者动态添加的控件未正确注册等)。 常见的解决方法包括: 1. 检查页面中是否存在动态添加的控件,并确保在页面的生命周期早期(如Page_Init)添加它们,以便事件验证可以正确注册它们。 2. 如果确实需要动态添加控件,并且这些控件会触发回发,那么需要在回发之前重新动态创建这些控件,并且创建的方式和数量必须与上一次请求一致。 3. 如果动态控件导致问题且难以解决,可以考虑禁用事件验证(但这不是推荐的安全做法),方法是在页面指令中添加EnableEventValidation="false"。 然而,根据用户的问题,他们希望保持事件验证启用(因为这是安全目的),所以我们需要寻找在启用事件验证的情况下解决问题的方法。 另外,错误信息中建议使用ClientScriptManager.RegisterForEventValidation方法来注册回发或回调数据以进行验证。因此,我们可以在动态添加控件后,手动注册这些控件的事件验证。 步骤: 1. 在动态创建控件时,为可能触发回发的控件(如按钮、下拉列表等)注册事件验证。 2. 在Render阶段之前(例如在OnPreRender事件中)调用RegisterForEventValidation方法。 但是,请注意,动态控件的创建必须在每次页面加载时都执行(包括回发),并且控件的ID必须保持一致。 另一种情况:如果错误是由于页面上的某些控件在回发时发送了不在服务器预期内的值(例如,一个下拉列表在回发时发送了一个不在原始数据项中的值),那么需要检查数据绑定是否正确,以及是否在回发时重新绑定了数据导致选项改变。 因此,解决方案可以归纳为: 1. 确保动态控件在Page_Init事件中创建。 2. 对于动态控件,如果它们有可能会产生回发值,那么在Page_Load之前(即Page_Init阶段)重新创建它们,并确保ID一致。 3. 对于动态控件的可能值,使用ClientScriptManager.RegisterForEventValidation方法进行注册(在Render阶段之前)。 示例:假设我们动态添加一个下拉列表(DropDownList),并给它添加一些列表项,然后这个下拉列表会触发回发。 我们需要在Page_Init中创建这个下拉列表,并且在每次页面加载时都创建相同的列表项。 然后,在下拉列表的每个列表项的值可能被回发的情况下,我们需要为每个值注册事件验证。 但是,注意:在ASP.NET中,当我们使用数据绑定并调用DataBind()方法时,事件验证会自动注册。因此,如果我们手动添加列表项而不使用数据绑定,则需要手动注册。 手动注册示例(在PreRender事件中): foreach (ListItem item in myDropDownList.Items) { Page.ClientScript.RegisterForEventValidation(myDropDownList.UniqueID, item.Value); } 然而,在ASP.NET 2.0及以上版本,对于动态添加的控件,如果是在Page_Init中添加的,并且列表项在每次回发时都相同,那么事件验证通常会自动处理。所以,只有当自动处理失败时,才需要手动注册。 另外,还有一些其他情况会导致此错误,例如: - 在页面中使用JavaScript修改了控件的值或选项,然后触发回发,而新的值或选项在服务器端并未注册。 - 跨页回发(Cross-page postback)也可能导致此问题。 如果问题由JavaScript引起,可以考虑: - 避免使用JavaScript修改可能回发的控件的选项或值。 - 如果必须修改,可以考虑在修改后重新注册事件验证(通过Page_Load中的服务端方法),但这通常难以实现,因为客户端修改的值在回发前服务器并不知道。 因此,针对用户的问题,我们可以给出以下解决方案: 解决方案1:确保动态控件在Page_Init中创建,并保持一致的ID和相同的列表项(如果是列表控件)。 解决方案2:如果动态控件在列表项上发生变化,并且这些变化是安全的,那么可以手动注册事件验证(在PreRender中)。 解决方案3:如果问题不是由动态控件引起,而是由其他原因(如视图状态损坏、控件树不一致等)引起,那么需要检查页面中其他控件的使用。 解决方案4:如果以上方法都无法解决,并且你确定页面是安全的,可以临时禁用事件验证(不推荐),方法是在页面指令中添加EnableEventValidation="false"。 但是,用户要求保持事件验证启用,所以我们重点提供前两种解决方案。 由于具体代码实现可能因页面逻辑而异,这里提供一个示例: 示例:动态创建下拉列表并注册事件验证 ```csharp protected void Page_Init(object sender, EventArgs e) { // 动态创建下拉列表 DropDownList ddl = new DropDownList(); ddl.ID = "DynamicDDL"; ddl.AutoPostBack = true; ddl.SelectedIndexChanged += new EventHandler(ddl_SelectedIndexChanged); // 添加列表项 ddl.Items.Add(new ListItem("Option 1", "1")); ddl.Items.Add(new ListItem("Option 2", "2")); // 将下拉列表添加到页面的某个容器(例如PlaceHolder) PlaceHolder1.Controls.Add(ddl); } protected void Page_PreRender(object sender, EventArgs e) { // 手动注册事件验证(如果自动注册不起作用,可以尝试手动注册) DropDownList ddl = (DropDownList)PlaceHolder1.FindControl("DynamicDDL"); if (ddl != null) { foreach (ListItem item in ddl.Items) { Page.ClientScript.RegisterForEventValidation(ddl.UniqueID, item.Value); } } } ``` 注意:在Page_Init中,我们创建了控件并添加了列表项。然后在Page_PreRender中,我们手动注册每个列表项的值。这样,当回发发生时,事件验证就会知道这些值是合法的。 但是,请注意,如果列表项很多或者动态控件很多,手动注册可能会增加开销。 另外,确保在每次回发时,动态控件都在Page_Init中重新创建,并且创建的方式和上一次请求一致(包括相同的ID和相同的列表项顺序和值)。 如果问题仍然存在,可能需要检查是否有其他控件导致问题,或者页面是否过于复杂导致视图状态问题。 最后,如果错误发生在用户控件中,也可以考虑在用户控件级别禁用事件验证(在用户控件的@Control指令中添加EnableEventValidation="false"),但这同样会降低安全性。 因此,我们优先推荐在保持事件验证启用的前提下,通过正确创建动态控件并手动注册事件验证来解决。 由于用户的问题描述中提到了使用&lt;pages enableEventValidation="true"/>或页面指令中的设置,说明他们希望保持事件验证启用,因此我们提供上述方法。 注意:在ASP.NET 4.0及更高版本中,事件验证机制有所改进,但基本方法相同。 如果上述方法不能解决,可能需要进一步检查具体页面代码。 由于这是一个常见的错误,我们可以生成一些相关问题,帮助用户进一步排查。 相关问题: 1. 如何正确处理ASP.NET中的动态控件以避免事件验证错误? 2.ASP.NET中,手动注册事件验证的注意事项有哪些? 3. 除了动态控件,还有哪些原因会导致'Invalid postback or callback argument'错误? 4. 如何在不禁用事件验证的情况下解决由JavaScript修改控件导致的事件验证错误? 5. 在用户控件中如何处理事件验证错误? 根据用户的具体情况,可以选择相应的问题进行深入。 &lt;/think>### 解决 "Invalid postback or callback argument" 错误的方法 当启用事件验证(通过 `&lt;pages enableEventValidation="true"/>` 或 `&lt;%@ Page EnableEventValidation="true" %>`)时出现此错误,表明 ASP.NET 检测到潜在的安全风险。以下是系统性的解决方案: #### 1. **理解核心问题** 事件验证是 ASP.NET 的安全机制,用于防止恶意用户篡改回发数据。当以下情况发生时触发此错误: - 客户端修改了服务器未预期的控件值(如下拉列表选项) - 动态添加的控件未正确注册 - 跨页回发或回调参数被篡改 - 视图状态损坏或未保持一致[^1] #### 2. **推荐解决方案** ```xml &lt;!-- 在 web.config 中禁用事件验证(不推荐) --> &lt;system.web> &lt;pages enableEventValidation="false"/> &lt;/system.web> &lt;!-- 或在页面指令中禁用 --> &lt;%@ Page EnableEventValidation="false" %> ``` > ⚠️ **警告**:禁用事件验证会降低安全性,仅作为最后手段 #### 3. **安全修复方案** **方法 1:动态控件正确注册** ```csharp // 在 Page_Init 中创建动态控件 protected void Page_Init(object sender, EventArgs e) { DropDownList ddl = new DropDownList(); ddl.ID = "dynamicDDL"; ddl.Items.Add(new ListItem("Option1", "1")); ddl.Items.Add(new ListItem("Option2", "2")); this.form1.Controls.Add(ddl); // 注册事件验证 foreach (ListItem item in ddl.Items) { Page.ClientScript.RegisterForEventValidation(ddl.UniqueID, item.Value); } } ``` **方法 2:验证回调参数** ```csharp // 在回调方法中验证参数 protected void CustomCallback(object sender, CallbackEventArgs e) { string param = e.Parameter; if (!IsValidParameter(param)) // 自定义验证逻辑 { throw new ArgumentException("Invalid callback parameter"); } // 处理逻辑 } ``` **方法 3:修复数据绑定** ```csharp // 确保回发时保持数据一致性 protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // 初始数据绑定 ddlItems.DataSource = GetItems(); ddlItems.DataBind(); } } ``` #### 4. **最佳实践** 1. **动态控件**: - 在 `Page_Init` 阶段创建 - 使用 `RegisterForEventValidation` 注册可能的值 - 保持控件ID一致 2. **数据绑定控件**: - 仅在 `!IsPostBack` 时初始绑定 - 避免回发时修改选项集合 3. **安全增强**: ```xml &lt;machineKey validationKey="AutoGenerate" decryptionKey="AutoGenerate" validation="SHA1"/> ``` #### 5. **调试步骤** 1. 检查事件日志获取异常详情 2. 使用 `ViewStateDecoder` 分析视图状态 3. 在 `Page_Error` 事件中记录验证失败参数: ```csharp protected void Page_Error(object sender, EventArgs e) { Exception ex = Server.GetLastError(); if (ex is ArgumentException && ex.Message.Contains("callback argument")) { Logger.Log($"Validation failed: {Request.Form}"); } } ``` > 关键原则:服务器呈现的控件状态必须与回发时的客户端状态严格一致[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值