asp.net-mvc SignalR + 通过操作方法将消息发布到集线器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7549179/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 01:29:22  来源:igfitidea点击:

SignalR + posting a message to a Hub via an action method

asp.net-mvcactionmessagesignalrsignalr-hub

提问by ollifant

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

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

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?

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

回答by Tim B James

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

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

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

对此还有另一个更新的答案,如SignalR Wiki 中所示

c#

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-serverfor changes.

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

If you are using DI container

如果您使用的是 DI 容器

If you are using a DI container to wire up your hubs, get IConnectionManagerfrom your container, and call GetHubContexton that connectionManager.

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

回答by DDan

2018 February, Short and simple solution

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

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.

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

回答by Judah Gabriel Himango

update 2012: 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.

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

update 2019Don't use this answer anymore. New versions of SignalR that work on AspNetCore should refer to the accepted answer by Tim B James, or other up-voted answers. I'm leaving this answer here for history's sake.

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



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

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

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

这是一个更新版本,显示了如何从 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!");
 } 

回答by J45

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

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

Then from your controller you can use

然后从你的控制器你可以使用

Hubs.ChatHub.Send(arg1, null);