65

我正在使用 SignalR ( https://github.com/SignalR/SignalR ) 的 hub- 功能向所有订阅的客户端发布消息:

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

这在通过 Javascript 调用“发送”时工作正常,但我也希望 Web 应用程序发布消息(从 ASP.NET MVC 操作方法中)。我已经尝试实例化一个新对象 ob NewsFeedHub 并调用 Send 方法,但这会导致错误(因为未设置集线器的底层“连接”)。有没有办法在没有连接的情况下使用集线器?

4

5 回答 5

98

请注意,自从提出此问题以来,SignalR API 已多次更改。有些答案可能会过时。这并不意味着它们应该被否决,因为它们在撰写本文时是正确的

如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

更新

此代码已更新。按照http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-server进行更改。

如果您使用的是 DI 容器

如果您使用 DI 容器来连接集线器,IConnectionManager请从您的容器中获取,然后调用GetHubContext该 connectionManager。

于 2012-06-19T10:09:30.333 回答
60

2018 年 2 月,简短的解决方案

为了解决这个问题,我通常按以下方式设计集线器:

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);
    }

}

所以很容易从 Javascript 和后端代码调用。这两种方法在客户端产生相同的事件。

于 2015-06-26T00:53:14.700 回答
10

2012 年更新这个答案也很旧!SignalR 的公共 API 似乎在不断变化。截至 2012 年 7 月,Tim B James 拥有新的、正确的 API 用法。

更新 2019不再使用此答案。在 AspNetCore 上工作的 SignalR 的新版本应参考 Tim B James 接受的答案,或其他投票赞成的答案。为了历史,我把这个答案留在这里。


Mike 当前接受的答案是旧的,不再适用于最新版本的 SignalR。

这是一个更新版本,显示了如何从 MVC 控制器操作向集线器发布消息:

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!");
 } 
于 2012-04-04T20:41:15.147 回答
4

我正在寻找.NET Core解决方案,谷歌把我发到这里,似乎没有人提到.NET Core解决方案,所以你去吧:

集线器,这里没什么特别的:

public class MyHub : Hub
{
    // ...
}

在你的内部controller

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

    public HomeController(IHubContext<MyHub> hub)
    {
        _hub = hub;
    }

    public IActionResult Index()
    {
        // ...
        await _hub.Clients.All.SendAsync("ReceiveMessage", "Hello from HomeController");
        // ...
    }
}
于 2021-02-26T11:00:18.307 回答
2

继 DDan 的回答之后,您可以创建一个重载的静态方法并将通用逻辑保留在一个方法中 - 我使用这种模式

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);
    }
}

然后从您的控制器中,您可以使用

Hubs.ChatHub.Send(arg1, null);
于 2017-05-16T09:52:55.987 回答