Asp.net

瀏覽器取消請求時的 ASP.NET Web API OperationCanceledException

  • March 3, 2014

當使用者載入頁面時,它會發出一個或多個 ajax 請求,這些請求會命中 ASP.NET Web API 2 控制器。如果使用者導航到另一個頁面,在這些 ajax 請求完成之前,這些請求會被瀏覽器取消。然後,我們的 ELMAH HttpModule 會為每個取消的請求記錄兩個錯誤:

錯誤一:

System.Threading.Tasks.TaskCanceledException: A task was canceled.
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
  at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
  at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
  at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
  at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext()

錯誤2:

System.OperationCanceledException: The operation was canceled.
  at System.Threading.CancellationToken.ThrowIfCancellationRequested()
  at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
  at System.Web.Http.WebHost.HttpControllerHandler.<CopyResponseAsync>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
  at System.Web.Http.WebHost.HttpControllerHandler.<ProcessRequestAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
  at System.Web.TaskAsyncHelper.EndTask(IAsyncResult ar)
  at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
  at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

查看堆棧跟踪,我看到從這裡拋出異常:https ://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Http.WebHost/HttpControllerHandler.cs# L413

我的問題是:如何處理和忽略這些異常?

它似乎在使用者程式碼之外……

筆記:

  • 我正在使用 ASP.NET Web API 2

  • Web API 端點是非同步和非非同步方法的混合。

  • 無論我在哪裡添加錯誤日誌,我都無法在使用者程式碼中擷取異常

    • 全球.asaxApplicaiton_Error
    • TaskScheduler.UnobservedTaskException
    • ELMAH 錯誤過濾void ErrorLog_Filtering( <https://code.google.com/p/elmah/wiki/ErrorFiltering> )

這是 ASP.NET Web API 2 中的一個錯誤,不幸的是,我認為沒有一種解決方法會始終成功。我們送出了一個錯誤來修復它。

最終,問題在於我們在這種情況下將取消的任務返回給 ASP.NET,而 ASP.NET 將取消的任務視為未處理的異常(它將問題記錄在應用程序事件日誌中)。

同時,您可以嘗試以下程式碼。它添加了一個頂級消息處理程序,該處理程序在取消令牌觸發時刪除內容。如果響應沒有內容,則不應觸發該錯誤。它發生的可能性仍然很小,因為客戶端可能會在消息處理程序檢查取消令牌之後但在更高級別的 Web API 程式碼執行相同檢查之前立即斷開連接。但我認為這在大多數情況下會有所幫助。

大衛

config.MessageHandlers.Add(new CancelledTaskBugWorkaroundMessageHandler());

class CancelledTaskBugWorkaroundMessageHandler : DelegatingHandler
{
   protected override async Task&lt;HttpResponseMessage&gt; SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   {
       HttpResponseMessage response = await base.SendAsync(request, cancellationToken);

       // Try to suppress response content when the cancellation token has fired; ASP.NET will log to the Application event log if there's content in this case.
       if (cancellationToken.IsCancellationRequested)
       {
           return new HttpResponseMessage(HttpStatusCode.InternalServerError);
       }

       return response;
   }
}

引用自:https://stackoverflow.com/questions/22157596