2012-11-27 29 views
14

我在我的MVC4應用程序中使用SignalR hub。 我加了ELMAH來處理所有的錯誤。 問題是發生在Hub中的錯誤沒有在ELMAH axd中記錄。 有沒有辦法配置它?如何使用SignalR配置ELMAH

回答

9

您必須添加HubPipelineModule,並確保您在您的errorLog元素中設置ApplicationName,否則Elmah將無法記錄錯誤,因爲它不會有HttpContext或AppName以記錄到。

<errorLog type="Elmah.SqlErrorLog, Elmah" applicationName="MyAppName" connectionStringName="myConnString" /> 

HubPipelineModule code I've used如下:

public class ElmahPipelineModule : HubPipelineModule 
{ 
    private static bool RaiseErrorSignal(Exception e) 
    { 
     var context = HttpContext.Current; 
     if (context == null) 
      return false; 
     var signal = ErrorSignal.FromContext(context); 
     if (signal == null) 
      return false; 
     signal.Raise(e, context); 
     return true; 
    } 

    private static void LogException(Exception e, IHubIncomingInvokerContext invokerContext) 
    { 
     var context = HttpContext.Current; 
     ErrorLog el = ErrorLog.GetDefault(context); 
     el.Log(new Error(e)); 
    } 

    protected override void OnIncomingError(Exception ex, IHubIncomingInvokerContext context) 
    { 
     var exception = ex; 
     if (ex is TargetInvocationException) 
     { 
      exception = ex.InnerException; 
     } 
     else if (ex is AggregateException) 
     { 
      exception = ex.InnerException; 
     } 

     if (!RaiseErrorSignal(exception)) 
      LogException(exception, context); 
    } 
} 

確保你的模塊添加到樞紐管道:

GlobalHost.HubPipeline.AddModule(new ElmahPipelineModule()); 

編輯

SignalR 2+

我注意到我最近的一個項目中沒有記錄我的SignalR異常,並且發現嘗試從當前上下文獲取ErrorSignal時引發了ArgumentNullException。以下方法正確處理此異常,以便再次記錄SignalR錯誤。

private static bool RaiseErrorSignal(Exception e) 
{ 
    var context = HttpContext.Current; 
    if (context == null) 
     return false; 

    try 
    { 
     var signal = ErrorSignal.FromCurrentContext(); 
     if (signal == null) 
      return false; 
     signal.Raise(e, context); 
     return true; 
    } 
    catch (ArgumentNullException) 
    { 
     return false; 
    } 
} 
+1

對於在最後一步遇到困難的其他人,將最後一行添加到RegisterHubs類中。例如:'public static void Start(){RouteTable.Routes.MapHubs(); GlobalHost.HubPipeline.AddModule(new Shopperscape.Web.API.ElmahPipelineModule()); }' – Chris

+0

@Chris這是否適用於SignalR 1.x? –

+1

@Giles - 此代碼適用於SignalR 1 – damienc88