【问题标题】:Intermittent "Failed to load viewstate" error间歇性“无法加载视图状态”错误
【发布时间】:2014-01-29 22:11:38
【问题描述】:

是的,我知道这个问题已被多次报告,但我的案例似乎不适合任何建议的解决方案(除非我遗漏了什么)。

ASP.NET 页面设置(简化)是:用户单击链接(技术上是 Infragistics WebDataTree 的一个节点),此操作将绑定位于 UpdatePanel 中的网格 (Infragistics WebHierarchicalDataGrid)。

现在这在本地测试系统中运行良好。当部署到生产服务器时 - 它也可以工作 - 大多数时候,但有时这会引发错误:

加载视图状态失败。视图状态所在的控制树 正在加载的必须与用于保存的控制树匹配 上一个请求期间的视图状态

如果生产系统负载较重(更多用户访问它),这种情况似乎会发生更多。同样,我没有构建任何动态控件,只是一个按钮和一个在按钮单击时填充的网格。

这可能是什么原因造成的?为什么这并不总是发生,而是有时?知道如何解决吗?

更新

这是确认的场景

  1. 如果一个用户访问并使用该页面 - 不会发生错误
  2. 如果两个用户执行相同的操作(甚至可以是来自同一客户端的 2 个浏览器会话)- 就会发生错误。

一个会话如何影响另一个会话的视图状态?

更新 2

应用程序部署到单个 Windows 2008/IIS7 服务器(无网络农场/网络花园,无负载平衡器)。运行时不会推出更新。

如果单个用户访问应用程序,它可以正常工作,但是当多个用户访问服务器时 - 最终其中一些用户会收到 ViewState 错误(而其他用户仍然可以正常工作)。他们都在做同样的事情——单击在 UpdatePanel 内触发网格重新绑定的树节点。他们使用不同的浏览器 - IE(9-11)、FF、Chrome - 随机用户/浏览器可能会发生错误

哦,我们也没有加密 ViewState。

更新 3

堆栈跟踪:

在 System.Web.UI.Control.LoadViewStateRecursive(Object savedState) 在 System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState) 在 System.Web.UI.Control.LoadViewStateRecursive(Object savedState) 在 System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState) 在 System.Web.UI.Control.LoadViewStateRecursive(对象已保存状态在 System.Web.UI.Control.LoadChildViewStateByID(ArrayList childState) 在 System.Web.UI.Control.LoadViewStateRecursive(Object savedState) 在 System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState) 在 System.Web.UI.Control.LoadViewStateRecursive(Object savedState) 在 System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState) 在 System.Web.UI.Control.LoadViewStateRecursive(Object savedState) 在 System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState) 在 System.Web.UI.Control.LoadViewStateRecursive(Object savedState) 在 System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState) 在 System.Web.UI.Control.LoadViewStateRecursive(Object savedState) 在 System.Web.UI.Control.LoadChildViewStateByIndex(ArrayList childState) 在 System.Web.UI.Control.LoadViewStateRecursive(Object savedState) 在 System.Web.UI.Page.LoadAllState() 在 System.Web.UI.Page.ProcessRequestMain(布尔值 includeStagesBeforeAsyncPoint,布尔型 includeStagesAfterAsyncPoint)

更新 4

如果我减小每次点击返回的数据的大小(例如 20 行而不是 100 行),问题似乎要么消失,要么出现的频率大大降低。

我尝试过操纵 ViewState - 例如将其拆分成块,使用 session 作为 ViewState 存储来减少实际发布的页面大小 - 没有任何效果。

【问题讨论】:

  • 检查您是否在使用自定义视图状态提供程序
  • 你能把页面的代码贴出来吗?听起来您有一些静态控件。
  • 整个代码发布起来非常复杂,如果有帮助,我可以发布片段,但基本上在单击事件处理程序中分配了网格数据源。没有静态(相当“共享”,因为它使用了 VB.NET 控件)所有控件都在 ASPX 标记中声明
  • 您可能没有任何明确的动态控件,但网格听起来是动态的,这意味着它正在构建一个应用视图状态的控件树。一个用户是否有可能更新网格的源(从而添加/删除记录,从而添加/删除有状态控件)?这将导致另一个用户的后续回发包含现在已过时的视图状态。
  • @TimMedora 这会在其他情况下导致问题吗?标准场景: 1. 用户点击按钮查看初始数据 2. 数据库中的数据发生变化 3. 用户再次点击按钮刷新网格中的数据

标签: asp.net runtime-error viewstate infragistics web-controls


【解决方案1】:

在关注this advice 了解如何调试我的代码之外的内容并获得对 Infragistics WebHierarchicalDataGrid DLL 及其源代码的调试符号的访问权限之后 - 结果是控件引发了异常 - 它与视图状态。在内部,在 1 元素数组代码中尝试访问第二个元素,抛出“IndexOutOfBound”异常,该异常经过神奇转换为向用户抛出的“无法加载视图状态”。

Infragistics 正在调查错误和修复它的方法,但由于时间紧迫,我们使用了以下解决方法:如果在异步回发结束时检测到“视图状态”错误 - 我们只需重新加载页面:

Sys.Application.add_load(appLoaded);

function appLoaded(sender, eventArgs) {
   Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequest)
}

function EndRequest(sender, args) {
    if (args.get_error() != undefined) {
        if (args.get_error().message.indexOf('Failed to load viewstate') != -1) {
            setTimeout(function () { location.reload(true) }, 100)
        }
    }
} 

是的,我确实意识到这就像用螺丝刀敲钉子一样优雅,但是由于错误是零星的,并且刷新会消除它 - 这是必须要做的。

【讨论】:

  • 多个用户同时访问该页面有什么区别? (顺便说一句,异常变成了“加载视图状态失败”,在加载视图状态时抛出,Web.UI.Control.LoadViewStateRecursive捕获所有IndexOutOfRangeExceptions,并抛出一个HttpException)
  • 感谢您的澄清。而且我仍然不确定为什么这只发生在比平常负载更重的情况下——我们能够用普通的负载测试器重现它。希望 Infragistics 能提出一些建议。
【解决方案2】:

您在生产中拥有多少台服务器? 如果有多个,您是否在 web.config 中设置 machineKey,以便所有服务器都使用相同的密钥来签署/验证 ViewState 值?

正如 Michael Liu 在评论中指出的那样,您不太可能会遇到 machineKey 问题的控制树错误。我仍然想知道您是否有多个服务器在生产中,因为您仍然可能遇到一个问题,即 ServerA 提供了较新版本的代码,然后 POST 返回到还没有的 ServerB新代码,所以控制树不匹配。如果您在网站上有活跃用户的情况下推出更改,即使使用单个服务器,从技术上讲,这种情况也可能发生。

【讨论】:

  • 机器密钥差异将导致视图状态 MAC 验证错误,而不是更改控制树错误。
  • 非常好。我仍然想知道这个人是否有多个服务器,因为这仍然可能表明一个或多个服务器有差异。代码,当你越过这些边界时,你可能会得到控制树错误。我会更新我的答案。
  • 更新了我的问题,不,我们不使用任何类型的东西。
  • 服务器上的不同版本是我们错误的原因stackoverflow.com/questions/6572247/…
【解决方案3】:

视图状态与会话状态无关。 但是,如果您尝试使用相同浏览器软件的 2 个实例的网站,则浏览器具有相同的会话。这为 IE>=8、firefox 和 chrome 附加。 尝试使用 2 种不同的浏览器(抱歉我的英语不好)

【讨论】:

  • 感谢您的回复,但在我的测试中,我使用的是 IE9 并从菜单中明确选择“新会话”。在实际场景中,这确实发生在多个客户端
【解决方案4】:

如果您使用负载平衡在生产环境中托管此内容,则当用户从一台服务器更改为另一台服务器时,可能会出现问题。这里的解决方案往往是在 web.config 中指定 machineKey。 Read more about it here at msdn.

<machineKey  
    validationKey="21F090935F6E49C2C797F69BBAAD8402ABD2EE0B667A8B44EA7DD4374267A75D7AD972A119482D15A4127461DB1DC347C1A63AE5F1CCFAACFF1B72A7F0A281B"           
    decryptionKey="ABAA84D7EC4BB56D75D217CECFFB9628809BDB8BF91CFCD64568A145BE59719F"
    validation="SHA1" decryption="AES" />

【讨论】:

  • 谢谢,我更新了我的问题 - 不,我们不使用负载均衡器
【解决方案5】:

似乎 UpdatePanel 导致视图状态出现问题。

更新:

为了调试,我会尝试记录发送给每个客户端的视图状态以及在部分回发期间从客户端接收的视图状态。

您可以将它们临时存储在与会话关联的数据库服务器上,如果没有异常,则在会话结束时清除它们。然后,如果您遇到此异常,请将其标记在数据库中,您可以比较服务器发送给客户端的内容和回发时收到的内容。您还可以在浏览器中手动加载这些值并重放它们以查看会发生什么。

客户端的视图状态被破坏,或者您的服务器正在发送无效的视图状态。

至少这会帮助你得到一些数据来调试。


这是一篇关于更新面板和一些可能有助于解决问题的替代 ajax 方法的文章:

http://msdn.microsoft.com/en-us/magazine/cc163413.aspx

其他一些可能的帮助:

http://lachlankeown.blogspot.com/2008/04/firefox-refresh-viewstate-updatepanel.html?m=1

http://weblog.west-wind.com/posts/2005/Jul/16/Invalid-ViewState

http://support.microsoft.com/default.aspx?scid=kb;EN-US;829743

【讨论】:

  • 感谢您的链接,我会审查它们。同时,我们必须使用 UpdatePanel,不幸的是不能禁用 ViewState。令人抓狂的是 - 如果多个用户没有点击该页面,该页面确实可以工作
【解决方案6】:

您的用户是否确实报告了问题,或者您只是在错误日志中看到它?我之前在用户取消浏览器上的请求时看到过这个错误,导致 ASP.NET 在尝试解析部分传输的请求时出错。如果视图状态恰好被部分传输,您可能会看到此错误。您的视图状态越大,您拥有的用户越多,您看到此错误的可能性就越大。您可以放心地忽略此错误。

您可以通过加载具有大量视图状态的页面并取消回发来测试这一点。

【讨论】:

  • 用户实际上报告了这个错误,所以很遗憾我们不能忽略它
【解决方案7】:

我曾经在我的一个项目中遇到过类似的问题。问题的原因是我们正在向表格控件添加动态控件,然后在提交页面时,表格将由不同的控件集填充。在深入研究该问题时,我们发现,如果在同一位置有其他一些控件,则主要是对于上一页上的下拉控件,视图状态将失败。

解决方案对我们来说非常简单,因为我们是动态创建控件的,无论如何它们每次都会被创建,所以我们只需将ViewState=false 转换为控件(在您的情况下为网格控件)。

根据您的评论,我认为您需要确定跨会话的内容对您来说是什么。当另一个用户登录时,很可能是第一个用户更改的数据。在这种情况下,您还应该考虑设置ViewState=false,或将网格绑定到page_Oninit,这样ViewState 就不会发生冲突。

希望这会有所帮助。

【讨论】:

  • 感谢您的回复,但我想重申一下,我们不使用动态控件,只是一个网格,在 ASPX 标记中声明,它绑定在回发上。您的问题是否也仅在服务器负载较重的情况下发生,而在正常情况下没有发生?
  • 您遇到的情况肯定有其他原因,但如果视图状态不冲突,它可能会变得无关紧要。如果两个用户打开您的网站,他们看到或可能会在网格中加载数据然后对其进行编辑,我没记错的话。数据是通用的,变化会影响所有人。如果是这种情况,您应该考虑我上面提到的两个建议中的任何一个。视图状态冲突发生在控件说网格最初被加载并且在绑定时发生回发时发现先前存在的行(例如 DataTable 行和因此控件)的结构已更改。
  • 没有编辑发生,网格是只读的。当用户单击不同的树节点时 - 网格绑定到不同的结果集(按行,列保持不变)。因此,每次用户单击时 - 他确实会在网格中看到不同的行,但通常不会导致任何问题。否则,如果每个绑定都带来新数据,任何绑定控件不会导致回发问题吗?
  • 对于非常特定的场景,视图状态会失败,而不是每次绑定。对我来说,在绑定秒时间用文本框替换下拉列表时失败了。 (并非所有控件都会发生这种情况[即,用文本框替换单选按钮不会导致任何问题。])。
【解决方案8】:

尝试使用ILSpy 反编译 dll,保存项目,构建它,然后链接该项目而不是 dll。这样您将获得完整的堆栈跟踪,并且可能更接近异常。

【讨论】:

  • 谢谢,我已经考虑过了。我现在正在尝试一种更简单的方法stackoverflow.com/a/580845/961695
  • 你运气好吗?通常步入 asp.net 是行不通的。但是 Red Gate 的 .Net Reflector 可以帮助您,该工具可以进入任何代码。
  • 我确实得到了 2 个堆栈跟踪步骤;他们导致 Infragistics DLL 内部出现“IndexOutOfBounds”错误,仍在调查中。
【解决方案9】:

我遇到了同样的问题,例如:点击一个会重定向我的按钮,然后在 IE 上按“旧”视图状态的后退按钮,而某些内容已更改。 在 IE、Chrome、Firefox 上,由于缓存,我遇到了这个问题。

为避免浏览器缓存您的页面,您可以在 url 中使用随机参数: 例如:“&ran=54921356”会随机生成。 看看这是否有帮助

我不知道您的 WebHierarchicalDataGrid 是如何绑定的,如果数据可以在回发和返回之间发生变化,则包装它的更新面板不应该启用视图状态。

我希望这会有所帮助!

PS:另外,我认为将视图状态存储在会话中是一个坏主意...

【讨论】:

  • 同意会话中的视图状态,仅将其作为测试以查看它是否有所作为。仍在尝试其他方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多