Call Signalr Core Hub Method from Controller

Call SignalR Core Hub method from Controller

Solution 1

Another possibility is to inject your HubContext into your controller like:

public VarDesignCommController(IHubContext<VarDesignHub> hubcontext)
{
HubContext = hubcontext;
...
}

private IHubContext<VarDesignHub> HubContext
{ get; set; }

Then you can also call

await this.HubContext.Clients.All.InvokeAsync("Completed", id);

But then you will direct call methods on all clients.

Solution 2

You can also work with typed hubs:
Simple create an interface where you define which methods your server can call on the clients:

public interface ITypedHubClient
{
Task BroadcastMessage(string name, string message);
}

Inherit from Hub:

public class ChatHub : Hub<ITypedHubClient>
{
public void Send(string name, string message)
{
Clients.All.BroadcastMessage(name, message);
}
}

Inject your the typed hubcontext into your controller, and work with it:

[Route("api/demo")]
public class DemoController : Controller
{
IHubContext<ChatHub, ITypedHubClient> _chatHubContext;
public DemoController(IHubContext<ChatHub, ITypedHubClient> chatHubContext)
{
_chatHubContext = chatHubContext;
}

// GET: api/values
[HttpGet]
public IEnumerable<string> Get()
{
_chatHubContext.Clients.All.BroadcastMessage("test", "test");
return new string[] { "value1", "value2" };
}
}

Call Signalr method from Controller .Net Core 2.1

I think you're misunderstanding how it all works together (which is the same thing I did up until yesterday), the hub code is for the client-side script code to call back into and then action, whereas the IHubContext is used as the strongly typed methods that will be sent to the Client-side

Hub

// This class is used by the JavaScript Client to call into the .net core application.
public class ChatHub : Hub<IChatClient>
{

public static ConcurrentDictionary<string, string> Connections = new ConcurrentDictionary<string, string>();

// As an example, On connection save the user name with a link to the client Id for later user callback
public override Task OnConnectedAsync()
{
var user = Context.User.Identity.Name;

Connections.AddOrUpdate(this.Context.ConnectionId, user, (key, oldValue) => user);

return base.OnConnectedAsync();
}

public override Task OnDisconnectedAsync(Exception exception)
{
// Do something on disconnect.
}

// Add other methods you want to be able to call from JavaScript side in here...
public void SendMessage(int id, string message)
{
// Message doing stuff here.
}
}

ChatClient Interface

// This provides strongly-typed methods that you'll have on the Client side but these don't exist on the server.
public interface IChatClient
{
//So this method is a JS one not a .net one and will be called on the client(s)
Task DoSomething(int id);

Task NotificationUpdate(int id, string message);
}

Controller

public class HomeController : Controller
{
private readonly IHubContext<ChatHub, IChatClient> _hubContext;

public HomeController(IHubContext<ChatHub, IChatClient> hubContext)
{
_hubContext = hubContext;
}

public async Task<ActionResult> Index(int id)
{

// This calls the method on the Client-side
await _hubContext.Clients.All.DoSomething(id);
}
}

How can I call the method that is in my Hub from my controller on ASP.NET Core?

A SignalR IHubContext provides a means of sending messages to your clients outside of a Hub instance. The sample at https://docs.microsoft.com/en-us/aspnet/core/signalr/hubcontext?view=aspnetcore-3.1 provides an example. Using the code there as a starting point, you can:

Inject the IHubContext into your controller, assuming that it is named HomeController:

public class HomeController : Controller
{
private readonly IHubContext<MyHub> _hubContext;

public HomeController(IHubContext<MyHub> hubContext)
{
_hubContext = hubContext;
}
}

Use the hub context in your PostOcorrencias controller action:

...
_context.Ocorrencias.Add(ocorrencia);
await _hubContext.Clients.All.SendAsync("RedesignMap");
await _context.SaveChangesAsync();
...

Call a hub method from a controller's action

The correct way is to actually create the hub context. How and where you do that is up to you, here are two approachs:

  1. Create a static method in your hub (doesn't have to be in your hub, could actually be anywhere) and then you can just call it via AdminHub.SendMessage("wooo")

    public static void SendMessage(string msg)
    {
    var hubContext = GlobalHost.ConnectionManager.GetHubContext<AdminHub>();
    hubContext.Clients.All.foo(msg);
    }
  2. Avoid the static method all together and just send directly to the hubs clients

        var hubContext = GlobalHost.ConnectionManager.GetHubContext<AdminHub>();
    hubContext.Clients.All.foo(msg);

SignalR: Unable to call Hub method from Controller

That's not how this works. When you call SendAsync that message is going out to the client. You don't call methods on your hub, via SendAsync. Nothing is happening, because the clients are literally getting sent a message that should invoke something listening for "SendMessage" client-side, which presumably is not something you've register your clients to listen for. If the goal is to hit "ReceiveMessage" client-side, then you should be doing SendAsync("ReceiveMessage", ...) in your controller.

How to call SignalR Hub Method that has Enum parameters with a Javascript Client?

Enum values are integers, surely passing integers should work?

Yes, just tested and it does work!

Define objects to match your Server-side enums

const CityEnum = {
LONDON : 101,
LISBON : 102,
RIO : 103,
SYDNEY : 104,
}

const FruitEnum = {
APPLES : 0,
BANANAS : 1,
ORANGES : 2,
}

//JS-Client:
const userName = "mind-mink";
const city = CityEnum.LONDON;
const fruit = FruitEnum.APPLES;

await _hubCnn.invoke("MyHubMethod", userName, city, fruit);


Related Topics



Leave a reply



Submit