信号R +通过操作方法将消息发布到 Hub

发布于 2024-12-06 13:52:13 字数 456 浏览 0 评论 0原文

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

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

怀念你的温柔 2024-12-13 13:52:13

请注意,自提出此问题以来,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那个连接管理器。

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.

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.

小帐篷 2024-12-13 13:52:13

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 和后端代码调用也很容易。这两种方法在客户端产生相同的事件。

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.

薄情伤 2024-12-13 13:52:13

2012 年更新这个答案也很旧了! SignalR 的公共 API 似乎在不断变化。 Tim B James 自 2012 年 7 月起已采用新的、正确的 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!");
 } 

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.

update 2019 Don'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.


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!");
 } 
洒一地阳光 2024-12-13 13:52:13

我一直在寻找 .NET Core 解决方案,Google 将我发送到这里,似乎没有人提到 .NET Core 解决方案,所以这里是:

The Hub,这里没什么特别的:

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

在您的控制器内部:

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

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

    public async Task<IActionResult> Index()
    {
        // ...
        await _hub.Clients.All.SendAsync("ReceiveMessage", "Hello from HomeController");
        // ...
    }
}

I was looking for .NET Core solution and Google sent me here, seems like no one mentioned .NET Core solution, so here you go:

The Hub, nothing fancy here:

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

Inside your controller:

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

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

    public async Task<IActionResult> Index()
    {
        // ...
        await _hub.Clients.All.SendAsync("ReceiveMessage", "Hello from HomeController");
        // ...
    }
}
芸娘子的小脾气 2024-12-13 13:52:13

根据 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);

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文