Search code examples
asp.net-coresignalrasp.net-core-2.0signalr.clientasp.net-core-signalr

AspNetCore.SignalR SendAsync not firing inside OnConnectedAsync


I am having an issue where I would like to send an event to the frontend whenever somebody is connected to the hub, but the notification is not being received on the front end. I think I may be confused between calling methods directly from the hub vs. utilizing the IHubContext. I was not able to find much information related to these versions, so your help will be greatly appreciated!

Package versions:

Server side (.Net Core 2.2): Microsoft.AspNetCore.SignalR (1.1.0)
Client side (React): @aspnet/signalr:1.1.0

So this is my example Hub:

public class MyHub: Hub<IMyHub>
{
    public override async Task OnConnectedAsync()
    {
        // This newMessage call is what is not being received on the front end
        await Clients.All.SendAsync("newMessage", "test");

        // This console.WriteLine does print when I bring up the component in the front end.
       Console.WriteLine("Test");

        await base.OnConnectedAsync();
    }

    public Task SendNewMessage(string message)
    {
        return Clients.All.SendAsync("newMessage", message);
    }
}

Now the working call I have so far is in a service, but that is sending "newMessage" like so:

public class MessageService: IMessageService
{
    private readonly IHubContext<MyHub> _myHubContext;

    public MessageService(IHubContext<MyHub> myHubContext)
    {
        _myHubContext = myHubContext;
    }

    public async Task SendMessage(string message)
    {
        // I noticed tis calls SendAsync from the hub context, 
        // instead of the SendMessage method on the hub, so maybe
        // the onConnectedAsync needs to be called from the context somehow also?
        await _myHubContext.Clients.All.SendAsync("newMessage", message);
    }
}

So the above service method call works and will contact the front end, this is an example of my front end connection in a react component:

const signalR = require('@aspnet/signalr');

class MessageComponent extends React.Component {
    connection: any = null;

    componentDidMount() {
        this.connection = new signalR.HubConnectionBuilder()
            .withUrl('http://localhost:9900/myHub')
            .build();

        this.connection.on('newMessage', (message: string) => {
            // This works when called from the service IHubContext
            // but not OnConncectedAsync in MyHub
            console.log(message);
        });

        this.connection.start();
    }

    componentWillUnmount() {
        this.connection.stop();
    }

    render() {
        ...
    }
}

Solution

  • This is because you are using a Strongly Typed Hub (https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-2.2#strongly-typed-hubs).

    I assume you defined SendAsync on your IMyHub interface and so the server is sending a message with method = SendAsync, arguments = "newMessage", "test". If you removed your IMyHub type then this will work as expected.