【问题标题】:user control event handler lost on postback用户控件事件处理程序在回发时丢失
【发布时间】:2010-11-18 14:40:39
【问题描述】:

我有一个名为 LeftMenu 的菜单用户控件,其中包含链接项的项目符号列表。它在 ascx 页面上:

<asp:BulletedList ID="PublisherList" DisplayMode="LinkButton" OnClick="PublisherList_Click" cssClass="Menu" runat="server"></asp:BulletedList>

我在if(!isPostBack)下的page_load中绑定列表

我在加载控件的页面上遇到问题。当页面首次加载时,事件处理程序会触发。但是,当页面回发时它不再触发,并且在 IE8 中,当我调试时,我在 Visual Studio 中得到“Microsoft JScript 运行时错误:预期对象”,指向“__doPostBack('LeftMenu$PublisherList','0') 。”在 FF 中我没有收到错误,但没有任何反应。我不是动态加载控件,它是使用以下方式加载到 aspx 页面上的:

<%@ Register TagPrefix="Standards" TagName="LeftMenu" Src="LeftMenu.ascx" %>

<Standards:LeftMenu ID="LeftMenu" runat="server"/>

关于我丢失事件处理程序的任何想法?

我刚刚意识到这也发生在我拥有的另一个用户控件上。一个文本框和一个按钮,我使用默认按钮来确保按下回车键使用该按钮。 .Net 将 html 中的内容转换为:

 <div id="SearchBarInclude_SearchBar" onkeypress="javascript:return WebForm_FireDefaultButton(event, 'SearchBarInclude_QuickSearchButton')">

所以只要我在框中输入一个键,我就会在“预期对象”行出现一个 javascript 错误。看来这两个问题是相关的。

再次编辑:我想我需要澄清一下。不是我点击菜单项,在回发时找不到所选项目。我有这个带有左侧导航的搜索页面,然后页面的主要内容会导致回发。这个回发一切都很好。一旦该页面被发回,现在如果我单击左侧导航中的项目符号列表,我会收到一个 javascript 错误并且它会失败。 LeftMenu 控件的 page_init 永远不会被调用。

【问题讨论】:

    标签: c# asp.net postback user-controls webforms


    【解决方案1】:

    听起来您可能会丢失点击,因为您没有在 PostBack 上对列表进行数据绑定。因此,回发试图引用一个不存在的控件(特定的项目符号列表项)。

    您应该尝试在 PostBack 上再次绑定列表,看看是否能解决您的问题。但是,真正应该发生的是 LeftMenu 和 BulletedList 应该将它们的信息存储到 ViewState 中,以便您可以确保在初始页面加载时向用户显示的数据与 PostBack 正在处理和使用的数据相同.

    【讨论】:

    • 如果菜单和列表包含 100 或 1000 个项目怎么办?它们是否仍应存储在视图状态中?
    • 理想情况下,ViewState 会死得很惨,永远不会回来,这样 PostBacks 的这些奥秘就永远不会抬起丑陋的脑袋,我们的页面保持轻盈通风 ;-) 话虽如此,这是一个左导航网站上的菜单,所以我怀疑项目不止几个。显然,如果这是某种数据库调用,您可能希望缓存它,这可能有助于保持页面调用轻量且不需要 ViewState,但您不能保证 PostBack 所处理的列表与用户看到的原始文件(如果缓存过期)。
    • 从 if(!isPostBack){...} 中删除它没有帮助。数据很少会发生变化,我是否仍将其存储在视图状态中?
    【解决方案2】:

    如果您的 UserControl 和其中的所有控件都有 EnableViewState=true,那么一切都应该正常工作。启用 ViewState 后,ASP 将在 Init 触发后从 ViewState 重新膨胀您的控件。这意味着回发事件 arg(指向控件列表中的索引)仍会在该列表位置找到控件。否则回发时列表为空。

    但是,ViewState 是魔鬼的杰作,其设计目的只是为了营造一种错觉,即您是在有状态的环境中工作。可以将它用于少量数据,但通常不建议用于重复器和列表等模板控件,因为您不知道在 ViewState 中将创建多少数据。

    如果您正在处理静态或相对静态的数据,请将其存储在应用程序缓存中并每次在 Page.Init 中重新绑定您的列表(注意它必须在 Init 中,因为 post-init 是 ASP 从 ViewState 重新绑定的时间; 如果您先进入,将使用您的数据)。

    如果您正在处理易失性数据,您会遇到问题,因为您重新绑定的数据必须与原始页面请求完全相同,否则回发事件将针对错误的行触发。在这种情况下,您需要将初始数据存储在 Session 中,或者您只需存储行 ID 列表(在隐藏变量或 Session 中),然后每次都重新创建要从 id 绑定的数据。

    更好的解决方案是根本不使用回发事件。尝试将所有事件转换为在查询字符串上具有 ID 的 GET。您仍然可以在第一次通过页面时使用绑定来创建列表(就像您当前所做的那样),您甚至可以使用新 ID 获取同一页面。

    如果您需要在同一页面上保持状态,但需要响应用户更改单选按钮选择(或其他内容),请考虑使用 Ajax 调用来更新屏幕。您还可以使用传递给 Ajax 调用的 ID 来执行此操作。

    一般来说,您使用有状态 ASP 的次数越多,您的页面就会变得越轻巧且响应速度越快。如有必要,您也可以更好地迁移到无状态 MVC。由于 ViewState 在您需要时不可用,因此您还可以节省大量用于调试晦涩问题的时间。

    我读过的对 ViewState 的最佳分析在下面的链接中。如果您完全了解它的工作原理,则可以继续使用它而不必产生任何费用。

    http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/truly-understanding-viewstate.aspx

    【讨论】:

    • 对不起,我想我解释得不够清楚。并不是我在回发中找不到所选项目,这在大多数情况下都有效。问题是当我在一个回发给自身的页面上拥有此控件时,然后尝试单击列表中的一个项目。我收到一个 javascript 错误“预期对象”,但它不起作用
    【解决方案3】:

    这可能与 javascript 相关,并且页面中较早加载的脚本引发错误并导致页面无法正确加载。

    您的用户控件是否将任何 javascript 加载到页面上?您可以在页面初始加载时检查 javascript 错误吗?

    【讨论】:

      【解决方案4】:

      我将代码移到我们现有的项目中,但出于某种奇怪的原因,我停止收到 javascript 错误,而是得到:

      “无效的回发或回调参数。事件验证在配置中使用&lt;pages enableEventValidation="true"/&gt;或在页面中使用&lt;%@ Page EnableEventValidation="true" %&gt;启用。

      出于安全目的,此功能验证回发或回调事件的参数是否源自最初呈现它们的服务器控件。如果数据有效且符合预期,请使用ClientScriptManager.RegisterForEventValidation 方法注册回发或回调数据以进行验证。"

      我还没有完全弄清楚我应该将注册事件验证与用户控件放在哪里,但同时我只是设置了enableeventvalidation=false,它现在似乎可以工作了。

      【讨论】:

      • 您是在本地机器上还是在开发/测试机器集群上运行它?如果您正在跳跃机器,则可能是机器密钥设置不正确以相互匹配。如果在您的机器上本地点击它,那么没关系:-)
      【解决方案5】:

      看起来 doPostBack 函数丢失了,因为它的参数是文字,所以它们不可能是原因。这是您自己的函数之一还是您的意思是调用 ASP __doPostBack 函数?

      查看 Firefox 错误控制台或允许在 IE 中进行脚本调试,看看究竟是什么对象找不到。更好的是,下载 Firebug 并进行调试。

      【讨论】:

        【解决方案6】:

        我遇到了类似的问题。事实证明,Akamai 正在修改用户代理字符串,因为正在应用不需要的设置。

        这意味着某些 .NET 控件无法正确呈现 __doPostBack 代码。此问题已在博客here

        【讨论】:

          猜你喜欢
          • 2010-11-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-07
          • 1970-01-01
          • 1970-01-01
          • 2010-12-27
          • 2017-12-16
          相关资源
          最近更新 更多