2014-02-15 120 views
12

我已經開發了基於ASP.NET 4.5 & Owin樣本signalR應用,SignalR,Owin和異常處理

,我已經託管在IIS 7.5的應用程序

一切正常,但我如何處理Owin中的異常?

考慮以下代碼:

[HubName("SampleHub")] 
public class SampleHub : Hub 
{ 
    public SampleHub() 
    { 
     throw new InvalidOperationException("?!"); 
    } 
} 

此異常不會調用的Application_Error(這是我的問題)

我在哪裏可以得到所有異常的owin用於記錄和調試目的像爲

Application_Error?

我不感興趣的東西是這樣的:

 app.UseErrorPage(new ErrorPageOptions() 
     { 
      ShowCookies = true, 
      ShowEnvironment = true, 
      ShowExceptionDetails = true, 
      ShowHeaders = true, 
      ShowQuery = true, 
      ShowSourceCode = true 
     }); 

這是高級的場景,像asp.net網頁API & asp.net的MVC

操作篩選與onException的方法完全無用爲了覆蓋的目的要好得多。

在此先感謝。

回答

19

如果你想專門爲SignalR Hubs提供異常處理,OWIN中間件是而不是要走的路。

爲了說明一個理由,假設SignalR在Hub方法內引發異常時使用WebSocket傳輸。在這種情況下,SignalR將不會關閉WebSocket連接。相反,SignalR將直接向套接字寫入一條JSON編碼消息,以向客戶端指出拋出異常。使用OWIN中間件沒有簡單的方法來觸發任何類型的事件,當發生這種情況可能包裝整個OWIN WebSocket Extension,我強烈建議不要。

幸運的是,SignalR提供了自己的Hub Pipeline,非常適合您的場景。

using System; 
using System.Diagnostics; 
using Microsoft.AspNet.SignalR.Hubs; 

public class MyErrorModule : HubPipelineModule 
{ 
    protected override void OnIncomingError(ExceptionContext exceptionContext, IHubIncomingInvokerContext invokerContext) 
    { 
     MethodDescriptor method = invokerContext.MethodDescriptor; 

     Debug.WriteLine("{0}.{1}({2}) threw the following uncaught exception: {3}", 
      method.Hub.Name, 
      method.Name, 
      String.Join(", ", invokerContext.Args), 
      exceptionContext.Error); 
    } 
} 

您可以使用ExceptionContext進行日誌記錄。例如,您可以將ExceptionContext.Error設置爲不同的異常,這將改變客戶端收到的異常。

甚至可以通過將ExceptionContext.Error設置爲null或通過設置ExceptonContext.Result來抑制異常。如果你這樣做,那麼對於客戶端來說,Hub方法返回你在ExceptonContext.Result中找到的值而不是拋出。

前陣子一個又寫了SO回答瞭如何可以調用一個客戶端回調由集線器方法拋出每一個例外:SignalR exception logging?

還爲HubPipelineModules MSDN文檔:http://msdn.microsoft.com/en-us/library/microsoft.aspnet.signalr.hubs.hubpipelinemodule(v=vs.118).aspx

+2

非常感謝爲你的好解決方案。 但是,此模塊無法記錄異常,如SignalR 的'集線器描述符提供程序的異常和'集線器激活程序'部分signalR模塊不會記錄集線器的構造函數異常。 你的模塊很有用,我將用它作爲SignalR記錄器。 但是SignalR的創建和啓動過程是由'Owin'本身執行的。我在哪裏可以得到這些例外。 暫時,我已經實現了SignalR的所有擴展點,如IHubDescriptorProvider,IHubActivator等,以使日誌成爲可能,這在我看來顯然是錯誤的。任何想法? –

+0

@ halter73它不適用於其他HubPipeLineModules方法或當前模塊的其他方法中引發的異常。 –

+1

感謝您的回答。當我在客戶端調用的集線器方法中拋出異常時,仍然無法調用「OnIncomingError」。它通過'GlobalHost.HubPipeline.AddModule()'註冊。爲什麼我的'HubPipelineModule'沒有被調用? – Artyom