Подтвердить что ты не робот

SignalR + отправка сообщения в концентратор через метод действия

Я использую хаб-функцию 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 и вызвать метод отправки, но это приводит к ошибке (поскольку базовое "соединение" концентратора не установлено). Есть ли способ использовать концентратор без подключения?

4b9b3361

Ответ 1

Обратите внимание, что интерфейс 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 в этом диспетчере соединений.

Ответ 2

2017 февраля, краткое и простое решение

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

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

Ответ 3

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

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

Ответ 4

После ответа от 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);