Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hub.Clients.User(userId).methodCall always throws Object reference not set to an instance of an object

I have a NotificationHub class which inherits from the Hub class.

public class NotificationHub : Hub
    {
        public void Send(string userId, Notification notification)
        {
            Clients.User(userId)
                .notificationReceived(notification);
        }
    }

This always fails with

[NullReferenceException: Object reference not set to an instance of an object.]
   Microsoft.AspNet.SignalR.Hubs.SignalProxy.Invoke(String method, Object[] args) +88
   Microsoft.AspNet.SignalR.Hubs.SignalProxy.TryInvokeMember(InvokeMemberBinder binder, Object[] args, Object& result) +12
   CallSite.Target(Closure , CallSite , Object , <>f__AnonymousType0`4 ) +351

However if I do this:

public class NotificationHub : Hub
    {
        public void Send(string userId, Notification notification)
        {
            var context = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();

            context.Clients.User(userId)
                .notificationReceived(notification);
        }
    }

It works .... what gives here? Most of the examples I've seen do not require getting the context explicitly, should it not already be available from Hub? I would rather not have to grab it explicitly every time.

Here is my IoC Setup:

GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => new SimpleInjectorHubActivator(container));
GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => new SignalRHubUserIdProvider());

Activator:

public class SimpleInjectorHubActivator : IHubActivator
    {
        private readonly Container _container;

        public SimpleInjectorHubActivator(Container container)
        {
            _container = container;
        }

        public IHub Create(HubDescriptor descriptor)
        {
            return (IHub) _container.GetInstance(descriptor.HubType);
        }
    }
like image 258
Jack Avatar asked Jun 18 '15 02:06

Jack


People also ask

How does SignalR hub work?

The SignalR Hubs API enables you to call methods on connected clients from the server. In the server code, you define methods that are called by client. In the client code, you define methods that are called from the server.

What is IHubContext?

The IHubContext is for sending notifications to clients, it is not used to call methods on the Hub . View or download sample code (how to download)

What is HUB in Azure SignalR?

In SignalR, a hub is a core component that exposes a set of methods that can be called by the client. In this section, you define a hub class with two methods: Broadcast : This method broadcasts a message to all clients. Echo : This method sends a message back to the caller.


1 Answers

If you want to send something to clients from outside of hub handler methods (ie not during handling message on server), you have to use GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();

Reason is that when the method is called to handle some client side message, hub instance is created by SignalR and Clients property is correctly initialized. This is not the case when you calling method yourself from server code (and probably creating hub instance yourself).

Imho error message is not very clear and this use case should be handled better by SignalR. Anyway for the same reason i suggest to separate all the methods sending messages to clients which are intended to be called from server code to different class (not derived from Hub).

like image 63
Michal Levý Avatar answered Oct 19 '22 22:10

Michal Levý