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.
CodePudding user response:
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.
CodePudding user response:
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");
}
}