【问题标题】:How to determine if current request is an asynchronous postback, in ASP.NET Application_Error event如何在 ASP.NET Application_Error 事件中确定当前请求是否为异步回发
【发布时间】:2012-01-23 20:29:13
【问题描述】:

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

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

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

【问题讨论】:

  • 抱歉,我们已经在使用 AllowCustomErrorsRedirect = false 并提供 AsyncPostBackErrorMessage。所以我不明白这篇文章是如何相关的。更新了问题以包括使用 OnAsyncPostBackError 处理程序。

标签: asp.net asyncpostbackerror


【解决方案1】:

Application_Error 方法中,您不再可以直接访问页面上的<asp:ScriptManager> 控件。所以现在处理它的AsyncPostBackError 事件为时已晚。

如果您想阻止重定向,您应该检查请求以查看它是否实际上是异步请求。 <asp:UpdatePanel> 会导致一个带有以下 HTTP 标头的回发:

X-MicrosoftAjax:Delta=true

(另见:ScriptManager Enables AJAX In Your Web Apps

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

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
}

至于什么是处理异常的适当方法是一个不同的问题恕我直言。

【讨论】:

  • 我担心查看 HttpRequest 标头将是唯一的解决方案。标题的可靠性如何?此外,这会干扰整页(非异步)回发吗?
  • 标头应该非常可靠,因为框架使用它来确定应如何发送响应。它不应该干扰同步回发,标题不会被设置或设置为Delta=false
  • 仅供参考 - 这种方法很有创意并且可能是可靠的,但实际上可以从 Application_Error 中访问 ScriptManager。详情见我的回答。
【解决方案2】:

我也遇到过类似的情况。对我有用的是在我的事件处理程序中为 ScriptManager 的 AsyncPostBackError 调用 Server.ClearError()。这可以防止调用 Global.asax Application_Error 函数。

【讨论】:

    【解决方案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 事件。

    【讨论】:

      猜你喜欢
      • 2011-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多