如何使用SignalR配置ELMAH

时间:2012-11-27 18:15:29

标签: signalr elmah

我在我的MVC4应用程序中使用SignalR hub。 我添加了ELMAH来处理所有错误。 问题是Hub中发生的错误没有记录在ELMAH axd中。 有没有办法配置它?

1 个答案:

答案 0 :(得分: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;
    }
}