I'm using SignalR hub in my MVC4 application. I added ELMAH to handle all errors. the problem is that errors which happen in the Hub are not being logged in ELMAH axd. Is there a way to configure it?
Asked
Active
Viewed 1,335 times
1 Answers
11
You have to add a HubPipelineModule
, and also ensure you set an ApplicationName in your errorLog element, Otherwise Elmah won't be able to log an error, as it won't have an HttpContext, or an AppName to log to.
<errorLog type="Elmah.SqlErrorLog, Elmah" applicationName="MyAppName" connectionStringName="myConnString" />
The HubPipelineModule code I've used is as follows:
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);
}
}
Make sure you add the module to the hub pipeline:
GlobalHost.HubPipeline.AddModule(new ElmahPipelineModule());
EDIT
SignalR 2+
I noticed none of my SignalR exceptions were being logged in a recent project I've been working on, and have found that an ArgumentNullException is thrown when trying to get the ErrorSignal from current context. The following method properly deals with this exception so that SignalR errors are being logged once again.
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;
}
}

damienc88
- 1,957
- 19
- 34
-
1For anyone else who gets stuck on the last step, add that last line into the RegisterHubs class. For example: `public static void Start() { RouteTable.Routes.MapHubs(); GlobalHost.HubPipeline.AddModule(new Shopperscape.Web.API.ElmahPipelineModule()); }` – Chris Sep 06 '13 at 21:36
-
Thanks. GlobalHost was something new in .NET 4 that I wasn't aware of. – Giles Roberts Apr 04 '14 at 09:17
-
For those using Autofac, this will help with the HubPipeline module: https://autofaccn.readthedocs.io/en/latest/integration/signalr.html#owin-integration. Also, on newer Elmah, the override of `OnIncomingError` gets an `ExceptionContext`. To get the exception, use `exceptionContext.Error`. – Alex May 20 '20 at 11:49