Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SignalR Hubs Clients are null when firing event

I've written a generic hubs which I'm having some issues with so to debug it I've decided to make a simple connection count like so:

public class CRUDServiceHubBase<TDTO> : Hub, ICRUDServiceHubBase<TDTO>
{
    public const string CreateEventName = "EntityCreated";
    public const string UpdateEventName = "EntityUpdated";
    public const string DeleteEventName = "EntityDeleted";

    protected int _connectionCount = 0;

    public Task Create(TDTO entityDTO)
    {
        return Clients.All.InvokeAsync(CreateEventName, entityDTO);
    }

    public Task Update(TDTO entityDTO)
    {
        return Clients.All.InvokeAsync(UpdateEventName, entityDTO);
    }

    public Task Delete(object[] id)
    {
        return Clients.All.InvokeAsync(DeleteEventName, id);
    }

    public override Task OnConnectedAsync()
    {
        this._connectionCount++;
        return base.OnConnectedAsync();
    }

    public override Task OnDisconnectedAsync(Exception exception)
    {
        this._connectionCount--;
        return base.OnDisconnectedAsync(exception);
    }
}

public class MessagesHub : CRUDServiceHubBase<MessageDTO>
{
    public MessagesHub() : base()
    {
    }
}

I'm registering this class like so:

services.AddTransient<ICRUDServiceHubBase<MessageDTO>, MessagesHub>();

I have a service who is using this, which I'm using it's implementation factory to subscribing to it's events:

services.AddTransient<IMessageDTOService>( (c) => {

    var context = c.GetRequiredService<DbContext>();
    var adapter = c.GetRequiredService<IAdaptable<Message, IMessageDTO, MessageDTO>>();
    var validator = c.GetRequiredService<IValidator<Message>>();
    var entityMetadataService = c.GetRequiredService<IEntityMetadataService<Message>>();

    var service = new MessageDTOService(context, adapter, validator, entityMetadataService);
    var hub = c.GetService<ICRUDServiceHubBase<MessageDTO>>();
    this.RegisterHubsCreate(service, hub);

    return service;
});

When I go to fire the event I get a null reference:

Microsoft.AspNetCore.SignalR.Hub.Clients.get returned null.

My best guess is that because the service is a dependency for the controller, It's created before signalR can initialize It's clients?

Does anyone have a suggestion on how I can register my events, and have a client populated?

like image 719
johnny 5 Avatar asked Nov 24 '17 02:11

johnny 5


Video Answer


1 Answers

I turns out I needed to Inject the IHubContext into my hubs to have access to the clients when I want to invoke server side.

protected IHubContext<CRUDServiceHubBase<TDTO>> _context;

public CRUDServiceHubBase(IHubContext<CRUDServiceHubBase<TDTO>> context)
{
    this._context = context;
}

public Task Create(TDTO entityDTO)
{
    return this._context.Clients.All.InvokeAsync(CreateEventName, entityDTO);
}
like image 135
johnny 5 Avatar answered Oct 05 '22 21:10

johnny 5