Please help, this is driving me crazy!
My Server -> SignalR (JS) Client method execution works fine via the SignalR pipeline, but not when called via a background service. I'm using ASP.NET MVC / Castle Windsor DI
I use a custom Dependency Resolver which I register during Owin Startup
I observe that via the NotificationHub (SignalR pipeline), Clients is resolved to a HubConnectionContext class:
However, via my background service, Clients resolves to a HubConnectionContextBase class:
... so I'm pretty sure it's a DI issue. I just can't see what I'm doing wrong. Also any tips to Debug would be greatly appreciated. Thanks
Application Start:
bootstrapper = ContainerBootstrapper.Bootstrap();
this.container = bootstrapper.Container;
var resolverSignalR = new DependencyResolverSignalR(container);
GlobalHost.DependencyResolver = resolverSignalR;
OwinConfig:
app.MapSignalR(url, DependencyResolverSignalR.CreateHubConfiguration());
DependencyResolverSignalR:
public class DependencyResolverSignalR : DefaultDependencyResolver
{
public static HubConfiguration CreateHubConfiguration()
{
var signalrDependencyResolver = new DependencyResolverSignalR(_container);
var configuration = new HubConfiguration {
EnableDetailedErrors = true,
Resolver = signalrDependencyResolver
};
return configuration;
}
private static IWindsorContainer _container;
public DependencyResolverSignalR(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException(nameof(container));
}
_container = container;
}
public override object GetService(Type serviceType)
{
return _container.Kernel.HasComponent(serviceType) ? _container.Resolve(serviceType) : base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
return _container.Kernel.HasComponent(serviceType) ? _container.ResolveAll(serviceType).Cast<object>() : base.GetServices(serviceType);
}
}
NotificationService: (runs via a loop every 10 seconds - AFTER client has connected)
// Not working
var hubContext = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
var clients = hubContext.Clients;
clients.All.receiveMessage(testMessage);
NotificationHub:
public override Task OnConnected()
{
var connectionId = Context.ConnectionId;
...
...
// Working fine
base.Clients.All.receiveMessage(testMessage);
return base.OnConnected();
}
Client:
omitted since it works fine via the signalr pipeline
I would expect the receiveMessage() client method called via the NotificationService to be executed on the client in exactly the same way it does when called via the SignalR pipeline. Instead nada. No error message, the call just silently does nothing.
I've even tried following the guide here (though it's geared towards Ninject) SignalR document to resolve the Clients (IHubConnectionContext) directly. Exactly the same result.
Code:
var resolverSignalR = new DependencyResolverSignalR(container);
container.Register(Component
.For<IHubConnectionContext<dynamic>>()
.UsingFactoryMethod(() =>
resolverSignalR.Resolve<IConnectionManager().GetHubContext<NotificationHub>().Clients));
Solved! It was an issue with the HubConfiguration - I'm not sure what exactly. But just bypassing it (which is possible because I'm already replacing the DependencyResolver in Application_Start()) fixed the issue.
Old OwinConfig:
app.MapSignalR(url, DependencyResolverSignalR.CreateHubConfiguration());
Replaced by:
app.MapSignalR();
but make sure you have something like this in Application_Start() (or wherever you initialise your DI container)
var resolverSignalR = new DependencyResolverSignalR(container);
GlobalHost.DependencyResolver = resolverSignalR;