SignalR + posting a message to a Hub via an action

2019-01-04 18:41发布

I am using the hub- feature of SignalR (https://github.com/SignalR/SignalR) to publish messages to all subscribed clients:

public class NewsFeedHub : Hub
public void Send(string channel, string content)
{
    Clients[channel].addMessage(content);
}

This works fine when calling "Send" via Javascript, but I would also like the web application to publish messages (from within an ASP.NET MVC action method). I already tried instantiating a new object ob NewsFeedHub and calling the Send method, but this results in an error (as the underlying "Connection" of the Hub is not set). Is there a way to use the Hub without a connection?

4条回答
【Aperson】
2楼-- · 2019-01-04 19:10

Please note that the SignalR API has changed multiple times since this question was asked. There is a chance that some answers will become out of date. This does not mean that they should be down-voted as they were correct at the time of writing

There is another updated answer for this, as seen in the SignalR Wiki

c#

Public ActionResult MyControllerMethod()
{
    var context = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
    context.Clients.All.methodInJavascript("hello world");
    // or
    context.Clients.Group("groupname").methodInJavascript("hello world");
}

vb.net

Public Function MyControllerMethod() As ActionResult
    Dim context = GlobalHost.ConnectionManager.GetHubContext(Of MyHub)()
    context.Clients.All.methodInJavascript("hello world")
    '' or
    context.Clients.Group("groupname").methodInJavascript("hello world")
End Function

Update

This code has been updated. Follow http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-server for changes.

If you are using DI container

If you are using a DI container to wire up your hubs, get IConnectionManager from your container, and call GetHubContext on that connectionManager.

查看更多
We Are One
3楼-- · 2019-01-04 19:26

Following on from DDan's answer you can create an overloaded static method and keep common logic in one method - I use this pattern

public class ChatHub : Hub
{
    private static IHubConnectionContext<dynamic> GetClients(ChatHub chatHub)
    {
        if (chatHub == null)
            return GlobalHost.ConnectionManager.GetHubContext<ChatHub>().Clients;
        else
            return chatHub.Clients;
    }

    // Call from JavaScript
    public void Send(string message)
    {
        Send(message, this);
    }

    // Call from C# eg: Hubs.ChatHub.Send(message, null);
    public static void Send(string message, ChatHub chatHub)
    {
        IHubConnectionContext<dynamic> clients = GetClients(chatHub);
        // common logic goes here 
        clients.All.receiveSend(message);
    }
}

Then from your controller you can use

Hubs.ChatHub.Send(arg1, null);
查看更多
【Aperson】
4楼-- · 2019-01-04 19:27

updated: This answer is old, too! SignalR's public API is in constant flux, it seems. Tim B James has the new, proper API usage as of July 2012.

The currently accepted answer from Mike is old, and no longer works with the latest version of SignalR.

Here's an updated version that shows how to post a message to a hub from an MVC controller action:

public ActionResult MyControllerMethod() 
{
     // Important: .Resolve is an extension method inside SignalR.Infrastructure namespace.
     var connectionManager = AspNetHost.DependencyResolver.Resolve<IConnectionManager>();
     var clients = connectionManager.GetClients<MyHub>();

     // Broadcast to all clients.
     clients.MethodOnTheJavascript("Good news!");

     // Broadcast only to clients in a group.
     clients["someGroupName"].MethodOnTheJavascript("Hello, some group!");

     // Broadcast only to a particular client.
     clients["someConnectionId"].MethodOnTheJavascript("Hello, particular client!");
 } 
查看更多
该账号已被封号
5楼-- · 2019-01-04 19:28

2018 February, Short and simple solution

For solving this I usually design my hubs in the following way:

public class NewsFeedHub : Hub 
{
    private static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<NewsFeedHub>();

    // Call this from JS: hub.client.send(channel, content)
    public void Send(string channel, string content)
    {
        Clients.Group(channel).addMessage(content);
    }

    // Call this from C#: NewsFeedHub.Static_Send(channel, content)
    public static void Static_Send(string channel, string content)
    {
        hubContext.Clients.Group(channel).addMessage(content);
    }

}

So it's easy to call from Javascript and from back-end code as well. The two methods are resulting in the same event at the client.

查看更多
登录 后发表回答