[英]Asynchronous error handling in MVC 5 filters
我已經創建了一個自定義過濾器屬性來擴展HandleErrorAttribute
,它捕獲所有異常。
我的整個應用程序都是圍繞整個堆棧中的異步架構構建的。 這意味着,我不得不異步使用OnException(ExceptionContext contect)
覆蓋。 像這樣的東西,就像我想象的那樣(簡化了可讀性):
public async override void OnException(ExceptionContext context)
{
base.OnException(context);
var logId = await LogException(e, httpContext); //LogException calls an async method and returns the ID of the exception, after it has been saved to the database. I this ID in the filterContext, which is why I need the result of the method
}
但是,這將導致InvalidOperationException: An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle
InvalidOperationException: An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle
。
我不能簡單地在同步調用時調用.Result,因為這會導致死鎖。
所以我想我的問題是:如何在MVC5中創建一個可以異步記錄錯誤的過濾器?
由於錯誤處理通常不是熱代碼,因此這里沒有性能問題。 因此,做最方便的事情。
例如,您可以阻止從LogException
返回的任務。 有多種方法可以可靠地避免死鎖。 一個簡單的方法是Task.Run(() => LogException()).Wait();
。 這是因為任務主體在沒有同步上下文的情況下運行。
您還可以在LogException
添加ConfigureAwait(false)
,但不能錯過任何一個地方。 這使得這很脆弱。
我建議你改變方法並實現自己的ExceptionLogger,因為它是用於記錄異常的ExceptionLogger作業
我們提供了兩個新的用戶可替換服務IExceptionLogger和IExceptionHandler來記錄和處理未處理的異常。 服務非常相似,有兩個主要區別:我們支持注冊多個異常記錄器,但只支持一個異常處理程序。 即使我們即將中止連接,也會始終調用異常記錄器。 只有當我們仍然可以選擇要發送的響應消息時,才會調用異常處理程序。 這兩種服務都提供對異常上下文的訪問,該異常上下文包含檢測到異常的相關信息,特別是HttpRequestMessage,HttpRequestContext,拋出的異常和異常源。
這里是示例代碼
public class ExceptionLogger : IExceptionLogger
{
public virtual Task LogAsync(ExceptionLoggerContext context,
CancellationToken cancellationToken)
{
return MyLogger.Log(context, cancellationToken);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.