2013-01-18 26 views
1

在我們的應用程序中,我們有一組相當簡單的日誌鉤子(MVC和API控制器上的IExceptionFilters以及Application_Error()中的附加catch-all),但是有一整類錯誤不會觸發它們中的任何一個。如果從WebAPI本身或內部使用的某個異常(例如由依賴解析程序創建的類的類型初始化程序)引發異常,則我得到的是發送給客戶端的500響應。應該如何處理內部web api錯誤?

我發現捕捉到錯誤的詳細信息的唯一方式是使用HttpConfiguration.IncludeErrorDetailPolicy配置發出錯誤的詳細信息的應用 - 然而,這是一個注意不好的做法,廣播你錯誤的詳細信息世界,所以我d更喜歡完全關閉它,或者將其設置爲有條件的(比如,僅限本地)。但是這意味着遠程運行到應用程序正在運行的服務器上,並使用可檢查響應的工具在本地調用API如IE或谷歌瀏覽器),以弄清楚發生了什麼事情。

我在這裏看到了另一個類似的問題(here),但是解決方案(使用DelegatingHandler檢查響應)不符合我們的需求,我們的想法。是否真的沒有可以掛鉤的事件,我可以使用的擴展點或類似的東西來捕獲發生的實際異常? (另外,我想我可以將IncludeErrorDetailPolicy更改爲Always,並使用其他線程中提供的解決方案來捕獲MessageHandler中的錯誤詳細信息,記錄它們並手動清理它們發送給客戶端,但這將是一個討厭的破解。)

想法? :/

+0

爲什麼MessageHandler方法不適合你? –

+0

我可能會誤解它,但是從我如何閱讀它中,獲取我可以記錄的異常對象的唯一方法是遵循我的問題結尾提到的黑客攻擊 - 在所有響應中啓用包含錯誤細節,然後解析錯誤詳細信息以嘗試重新構造最初拋出的異常,然後在將響應發送到客戶端之前手動清理響應中的這些細節。 ..雖然這應該起作用,但聽起來很粗糙,脆弱,並且傾向於丟失診斷信息和/或無意中將該信息泄露給客戶。 –

+0

您想保留診斷信息*和*避免信息泄露給客戶?你想回復什麼樣的回答?爲什麼默認值不適合你?您將在本地計算機上獲得完整的診斷信息以進行調試,並且沒有任何信息泄露給遠程客戶端。 –

回答

0

好吧,我明白你想要做什麼。感謝澄清。 WebAPI有一個模型,錯誤響應不一定是由異常引起的。任何人都可以返回一個帶有400的HttpResponseMessage,而不用實際拋出異常。而且在很多情況下,內置的框架錯誤以相同的方式工作,而不會引發異常。

現在,我認爲你的建議對我來說聽起來很好。您可以將ErrorDetailPolicy設置爲始終,並實現一個消息處理程序,記錄錯誤並使用不同的僅包含消息的HttpError。下面是它可能看上去是這樣的:

public class ErrorHandlingMessageHandler : DelegatingHandler 
{ 
    protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     HttpResponseMessage response = await base.SendAsync(request, cancellationToken); 
     HttpError error; 
     if (response.TryGetContentValue(out error)) 
     { 
      LogError(error) 
      // Use an HttpError that doesn't leak internal information 
      (response.Content as ObjectContent).Value = new HttpError(error.Message); 
     } 

     return response; 
    } 
} 

請注意,我們不擦洗現有的錯誤。我們正在創建一個新的來減少信息泄露的風險。該消息應始終安全地發回。這不包括髮送模型狀態,但是如果您需要,您可以隨時將其複製到新錯誤。

想到這一點的一種方法是,您可以記錄您將發送給本地客戶端的響應,然後向遠程客戶端發送不包含錯誤詳細信息的安全消息。

1

我們向微軟合作伙伴網絡提出了一項支持請求,他們回來後我覺得這是一個更好的答案。

這個想法是將平臺的默認IHttpControllerActivator實現替換爲默認控制器創建行爲與任何其他所需行爲的實現。

在我們的例子中,這意味着用一個try/catch/throw構造和對我們的日誌服務的調用來包裝DefaultHttpControllerActivator的Create方法。這可能不會提供100%的覆蓋率,但是我們遺漏的大多數例外與處理器的創建有關,所以它應該有很大的幫助。

我真的很喜歡能夠鉤住HttpControllerDispatcher中的HandleException方法,但它既是私有的也是靜態的,所以meh。

+0

+1,只是一句話:爲了完全控制這些內部錯誤,還要替換IHttpControllerSelector,IHttpActionSelector和IHttActionInvoker。 – Konamiman