在 ASP.NET Application_Error事件中,如何确定当前请求是否为异步回发

How to determine if current request is an asynchronous postback, in ASP.NET Application_Error event

提问人:BlueFox 提问时间:1/24/2012 最后编辑:BrianFinkelBlueFox 更新时间:2/13/2013 访问量:4510

问:

是否可以从Application_Error事件中确定当前请求是否是异步回发(部分页面更新)?

使用异步回发时处理应用程序错误的最佳方法是什么?

在 Application_Error 中,我们将重定向到不同的错误页面,但是在异步回发期间引发错误时,这将无法正常工作。我们注意到,即使 AllowCustomErrorsRedirect = false,这也成立,并且我们有一个 OnAsyncPostBackError 处理程序来设置 AsyncPostBackErrorMessage。在异步回发期间,我们的 AsyncPostBackErrorMessage 将被覆盖,客户端会收到一个通用网页错误。

asp.net asyncpostbackerror

评论

0赞 Tim Schmelter 1/24/2012
codedigest.com/Articles/ASPNETAJAX/......
0赞 BlueFox 1/24/2012
抱歉,我们已经在使用 AllowCustomErrorsRedirect = false 并提供 AsyncPostBackErrorMessage。所以我看不出这篇文章有什么意义。更新了问题,以包括使用 OnAsyncPostBackError 处理程序。

答:

8赞 Michiel van Oosterhout 1/24/2012 #1

在该方法中,您不再能够直接访问页面上的控件。因此,处理其 AsyncPostBackError 事件为时已晚。Application_Error<asp:ScriptManager>

如果要阻止重定向,则应检查请求以查看它是否实际上是异步请求。这会导致回发,并显示以下 HTTP 标头:<asp:UpdatePanel>

X-MicrosoftAjax:Delta=true

(另请参阅:ScriptManager 在 Web 应用中启用 AJAX)

对此标头的检查如下所示:

HttpRequest request = HttpContext.Current.Request;
string header = request.Headers["X-MicrosoftAjax"];
if(header != null && header == "Delta=true") 
{
  // This is an async postback
}
else
{
  // Regular request
}

至于处理异常的适当方法是另一个问题,恕我直言。

评论

0赞 BlueFox 1/24/2012
恐怕研究HttpRequest标头是唯一的解决方案。标头的可靠性如何?此外,这会干扰整页(非异步)回发吗?
0赞 Michiel van Oosterhout 1/24/2012
标头应该非常可靠,因为框架使用它来确定应如何发送响应。它不应干扰同步回发,标头不会被设置或设置为Delta=false
0赞 BrianFinkel 2/13/2013
仅供参考 - 这种方法很有创意,可能很可靠,但实际上可以从 Application_Error 中访问 ScriptManager。有关详细信息,请参阅我的答案。
1赞 jcj80 6/29/2012 #2

我也有类似的情况。对我有用的是调用我的事件处理程序来调用 ScriptManager 的 .这样可以防止调用 Global.asax 函数。Server.ClearError()AsyncPostBackErrorApplication_Error

0赞 BrianFinkel 2/13/2013 #3

在 Application_Error 中,您实际上可以访问 ScriptManager 来确定当前请求是否为异步回发。全局对象 HttpContext.Current.Handler 实际上指向正在服务的页面,其中包含 ScriptManager 对象,该对象将告诉您当前请求是否是异步的。

以下语句简明扼要地说明了如何访问 ScriptManager 对象并获取此信息:

ScriptManager.GetCurrent(CType(HttpContext.Current.Handler, Page)).IsInAsyncPostBack

当然,如果当前请求不是针对某个页面,或者当前页面上没有 ScriptManager,则该语句将失败,因此,下面是一对更可靠的函数,可以在 Global.asax 中使用来做出决定:

Private Function GetCurrentScriptManager() As ScriptManager
    'Attempts to get the script manager for the current page, if there is one

    'Return nothing if the current request is not for a page
    If Not TypeOf HttpContext.Current.Handler Is Page Then Return Nothing

    'Get page
    Dim p As Page = CType(HttpContext.Current.Handler, Page)

    'Get ScriptManager (if there is one)
    Dim sm As ScriptManager = ScriptManager.GetCurrent(p)

    'Return the script manager (or nothing)
    Return sm
End Function

Private Function IsInAsyncPostback() As Boolean
    'Returns true if we are currently in an async postback to a page

    'Get current ScriptManager, if there is one
    Dim sm As ScriptManager = GetCurrentScriptManager()

    'Return false if no ScriptManager
    If sm Is Nothing Then Return False

    'Otherwise, use value from ScriptManager
    Return sm.IsInAsyncPostBack
End Function

只需从 Application_Error 中调用 IsInAsyncPostback() 即可获取指示当前状态的布尔值。

您在客户端上收到通用 ASP.NET 错误,因为尝试传输/重定向异步请求将生成更多错误,从而替换并混淆原始错误。在这种情况下,您可以使用上面的代码来防止传输或重定向。

另请注意我的另一个发现:即使您可以使用此方法访问 ScriptManager 对象,但由于某种原因,从Application_Error中设置其 AsyncPostBackErrorMessage 属性不起作用。新值不会传递给客户端。因此,您仍需要在页面类中处理 ScriptManager 的 OnAsyncPostBackError 事件。