SignalR + отправка сообщения в Hub с помощью метода действия - PullRequest
61 голосов
/ 26 сентября 2011

Я использую хаб-функцию SignalR (https://github.com/SignalR/SignalR) для публикации сообщений всем подписанным клиентам:

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

Это прекрасно работает при вызове «Отправить» через Javascript, но я бытакже как веб-приложение для публикации сообщений (из метода действия ASP.NET MVC). Я уже пытался создать экземпляр нового объекта ob NewsFeedHub и вызвать метод Send, но это приводит к ошибке (в качестве основного «соединения»Концентратор не установлен). Есть ли способ использовать концентратор без подключения?

Ответы [ 4 ]

90 голосов
/ 19 июня 2012

Обратите внимание, что API SignalR менялся несколько раз с тех пор, как был задан этот вопрос. Есть вероятность, что некоторые ответы устареют. Это не означает, что за них следует проголосовать отрицательно, так как они были правильны на момент написания

Существует еще один обновленный ответ на этот вопрос, как видно из SignalR Wiki

с #

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.

55 голосов
/ 26 июня 2015

2018 февраль, Краткое и простое решение

Для решения этой проблемы я обычно проектирую свои концентраторы следующим образом:

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 и из внутреннего кода, а также.Два метода приводят к одному и тому же событию на клиенте.

10 голосов
/ 05 апреля 2012

обновление 2012 : Этот ответ тоже старый!Кажется, публичный API SignalR постоянно меняется.Тим Б Джеймс имеет новое, правильное использование API по состоянию на июль 2012 года.

обновление 2019 Больше не используйте этот ответ.Новые версии SignalR, которые работают на AspNetCore, должны ссылаться на принятый ответ Тима Б. Джеймса или другие ответы с повышенным голосованием.Я оставляю этот ответ здесь ради истории.


В настоящее время принятый ответ от Майка устарел и больше не работает с последней версией 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!");
 } 
2 голосов
/ 16 мая 2017

Исходя из ответа 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);
...