skip to Main Content

I’m trying to use SignalR to send an update through a websocket when a request is made to an endpoint. But, I’m struggling to inject the relevant Controller with a hub dependency. I’ve got a controller with the following GET function:

[HttpGet]
public IEnumerable<Zaal> GetZaal()
{
    new BoekingUpdateHub().SendData("Test");
    foreach(Stoel s in _context.Stoel)
    {
        Console.WriteLine(s.Id);
    }
    return _context.Zaal;
}

Problem is, when I try to use this endpoint, the hub is not instantiated properly, as

public class BoekingUpdateHub : Hub
{
    public async Task SendData(string data)
    {
        await Clients.All.SendAsync("ReceiveData", data);
    }
}

Gives me a null reference exception on the await Clients.All, as Clients was null

I’ve tried using dependency injection to resolve this problem, but it gives me:

System.InvalidOperationException: Unable to resolve service for type
‘WDPR.Hubs.BoekingUpdateHub’ while attempting to activate
‘WDPR.Controllers.ZaalController’.

I’ve looked around and I can’t find a solution, I’m completely lost on how to implement this properly.

2

Answers


  1. Chosen as BEST ANSWER

    I figured it out. Rather than putting the Hub as an argument in the constructor, you add IHubContext as an argument, in this case the T is the Hub you want to actually use (in my case the hub is called MyHub)

    private readonly DbTheaterLaakContext _context;
    private readonly IHubContext<MyHub> _hubContext;
    
    public ZaalController(DbTheaterLaakContext context, IHubContext<BoekingUpdateHub> hubContext)
    {
        _context = context;
        _hubContext = hubContext;
    }
    

    Then, you can create the Hub inside one of the Endpoint functions:

    [HttpGet]
    public IEnumerable<Zaal> GetZaal()
    {
        new MyHub(_hubContext).SendData("Zaal GET request received");
    }
    

    Finally, make sure the IHubContext is an argument in the Hub's constructor:

    public class MyHub: Hub
    {
        protected IHubContext<MyHub> _context;
    
        public MyHub(IHubContext<MyHub> context)
        {
            this._context = context;
        }
        public async Task SendData(string data)
        {
            await _context.Clients.All.SendAsync("ReceiveData", data);
        }
    }
    

    Now, notice we're using the IHubContext as a source for our Clients, this prevents the Clients from being null. Doing these steps allows you to send information through a SignalR websocket when an endpoint receives a request.


  2. Configure the controller as follows

    public class DemoController : ControllerBase
    {
      private readonly IHubContext<MyHub> _hubContext;
      public DemoController(
            IHubContext<MyHub> hubContext
            )
        {
            _hubContext = hubContext;
        }
    
      [HttpGet]
      public IEnumerable<Zaal> GetZaal()
      {
        _hubContext.Clients.All.SendData("Zaal GET request received");
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search