3

I'm using signalR 1.0.0-alpha2-final and want to send a message to all connected clients.

I have used this tutorial as a starting point.

I have my RulesHub that inherits from Hub:

[EnableCors("MyPolicy")]
public class RulesHub : Hub
{
    private readonly IRuleService _ruleService;

    public RulesHub(IRuleService ruleService)
    {
        _ruleService = ruleService;
    }

    public Task Send()
    {
        var rules = _ruleService.RulesMonitoring();
        return Clients.All.InvokeAsync("SendRules", rules);
    }
}

On the frontend I have this code in order to connect to the Hub:

let connection = new signalR.HubConnection(rulesMonitorUrl);

connection.on('SendRules', function(data:any){
    console.log(data);
});

And after connecting one client, I'm calling the Send method from this controller:

[EnableCors("MyPolicy")]
Route("api/[controller]")]
public class MyController : Controller
{
    private readonly IMyService _myService;
    private RulesHub _rulesHub;

    public MyController(IMyService myService, IRuleService ruleService)
    {
        _myService = myService;
        _rulesHub = new RulesHub(ruleService);
    }

    [HttpPost]
    public void Post([FromBody]MyClass myClass)
    {
        _myService.Add(myClass);
        _rulesHub.Send();
    }
}

But the line return Clients.All.InvokeAsync("SendRules", rules); is failing with the following exception message:

System.NullReferenceException: 'Object reference not set to an instance of an object.'

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

I have read that in ASP.NET you should use something like IHubContext context = GlobalHost.ConnectionManager.GetHubContext("MyChatHub"); but this is not working on this version.

Any ideas?

joacoleza
  • 775
  • 1
  • 9
  • 26

1 Answers1

4

This is a duplicate question: Call SignalR Core Hub method from Controller

You should never ceate an instance of a hub by yourself. Simple inject it into your controller like:

[EnableCors("MyPolicy")]
Route("api/[controller]")]
public class MyController : Controller
{
    private readonly IMyService _myService;
    private  IHubContext<RulesHub> _rulesHubContext;    

    public MyController(IMyService myService, IRuleService ruleService, IHubContext<RulesHub > rulesHubContext)
    {
        _myService = myService;
        _rulesHubContext = rulesHubContext;
    }

    [HttpPost]
    public void Post([FromBody]MyClass myClass)
    {
        _myService.Add(myClass);
        // Load your rules from somewhere 
        _rulesHubContext.Clients.All.InvokeAsync("SendRules", rules);
    }
}
Stephu
  • 3,236
  • 4
  • 21
  • 33
  • 1
    Hi, thanks for commenting. The question you shared seems to be for another signalR version, I can't use Microsoft.AspNetCore.SignalR.Infrastructure. I tried the code you shared, but it doesn't work for me. The client is not getting the rules. I don't understand what should be implemented on RulesHub now with the changes you suggested, since the only method the class had would no longer be used. – joacoleza Nov 05 '17 at 20:34
  • @jaocoleza Did your tried my solution. You can let your hub empty. The hub is required for the connection. You can add to the hub methods which the client can execute on the server – Stephu Nov 05 '17 at 20:42
  • I have the Hub empty now and I'm calling _rulesHubContext.Clients.All.InvokeAsync("SendRules", rules); from the controller, but the client is not getting the info. There is a way to check the clients of the Hub? Just to verify that the connection is there. – joacoleza Nov 05 '17 at 20:46
  • Also, I had to change _private RulesHub _rulesHub;_ for _private IHubContext _rulesHubContext;_ and _rulesHubContext.All.InvokeAsync("SendRules", rules);_ for __rulesHubContext.Clients.All.InvokeAsync("SendRules", rules);_ – joacoleza Nov 05 '17 at 21:00
  • @joacoleza: You can override the OnConnectedAsync on your hub. There you can add a breakpoint. Then you will see if a clients connects to the hub: public override Task OnConnectedAsync() { ... } – Stephu Nov 05 '17 at 21:11
  • @joacoleza sorry my mistake. I wrote to fast. It's no corrected – Stephu Nov 05 '17 at 21:12
  • I override that method and the breakpoint inside is never beign hit. Maybe I have something wrong on the frontend? Maybe the startup.cs? – joacoleza Nov 05 '17 at 21:18
  • It's on the question. I run that code when a button is clicked and then with postman I call my endpoint on the controller. Then, I expect a log on the browser console, but nothing happens. – joacoleza Nov 05 '17 at 21:25
  • @jaocoleza I do not see that you start the connection there – Stephu Nov 05 '17 at 21:51
  • Wow, silly mistake on my part. It's working now, thanks for the help!! – joacoleza Nov 05 '17 at 22:06
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/158280/discussion-between-tester-and-joacoleza). – Stephu Nov 05 '17 at 23:14