Передать значение параметра клиенту - PullRequest
0 голосов
/ 11 октября 2018

У меня есть кнопка, которая при нажатии будет / должна уведомить сервер.Затем сервер сохранит значение в базе данных.Если все прошло хорошо, он должен вернуть true, в противном случае вернуть false.

Я создаю экземпляр концентратора на мой взгляд

var signalRhub = $.connection.hubSignalR;    

Начать соединение:

    $.connection.hub.start().done(function () {
        $("#submitBut").click(function () {
             signalRhub.server.cardAdded();
        });            
    });

Определитьфункция, которая будет использоваться сервером для возврата логического значения:

signalRhub.client.cardAddedRes = function (isSuccess) {
     alert("From server: " + isSuccss);
}

Мой класс хаба:

public class HubSignalR : Hub
{
    public bool isSuccess = false; <-- Will be set from controller

    public void CardAdded() 
    {
        Clients.Caller.CardAddedRes(isSuccess);  <-- Notice the isSuccess
    }
}

Моя проблема в том, что значение isSuccess исходит от моего контроллера,который взаимодействует с моделью / базой данных.Итак, я получаю сообщение об ошибке:

Using a Hub instance not created by the HubPipeline is unsupported.

Я пытался использовать: GlobalHost.ConnectionManager.GetHubContext<HubSignalR>(), но не могу заставить его работать.

Вот соответствующий код в моемконтроллер:

private HubSignalR signalR = new HubSignalR(); <-- Field variable

 [HttpPost]
 public ActionResult AttachCard(Card model, int MemberID)
 {
  var hub = GlobalHost.ConnectionManager.GetHubContext<HubSignalR>();
  ...
  //We saved to the database, so we call the client function with bool = true   
  hub.Clients.All.CardAdded(true);  <-- Actually I want to send to one client, NOT ALL
  //Something like hub.Clients.Caller.CardAdded();
  }

Я вынужден заполнить поле isSuccess в своем классе: HubSignalR, так как мне нужно вернуть его в качестве параметра из моего контроллера.Но когда кнопка нажата, это значение еще не было установлено (я думаю).

Я вижу из отладчика, что я достигаю: signalRhub.server.cardAdded(); Но сервер никогда не отвечает, поэтому я неЯ не могу достичь этой функции:

    signalRhub.client.cardAddedRes = function (isSuccess) {
     alert("From server: " + isSuccss);
}

Мне не удается вызвать метод CardAdded() с моего контроллера, например, GlobalHost.ConnectionManager.GetHubContext.Но вы можете видеть

Если у вас есть более хорошее решение, чем то, что я пытаюсь сделать, пожалуйста, сообщите.Я совершенно новый с SignalR и довольно новый с ASP.net MVC

1 Ответ

0 голосов
/ 11 октября 2018

Надеюсь, я правильно понял проблему: вы хотите установить isSuccess в контроллере и отправить его конкретному клиенту, но не достигаете определенного клиента извне концентратора?

Что касается "как":

Вы должны найти способ идентифицировать вашего клиента, то есть реализовать какую-то аутентификацию.Подробнее об этом здесь: Аутентификация в .net core Когда клиенты подключаются к SignalR, они получают идентификатор подключения.Вы можете сопоставить идентификатор соединения с реальной идентификацией клиента.Более подробная информация здесь: Отображение клиентов на соединения

Чем в вашем сервере метод:

  • Получить аутентифицированную идентификацию клиента
  • Получить контекст концентратора signalR
  • Сопоставить идентификатор клиента с существующим идентификатором соединения signalR
  • Отправить сообщение этому соединению signalR

Как я вижу из вашего кода, вы, возможно, работаете над каким-то личным использованием/ исследовательский проект и, вероятно, не заинтересованы в реализации аутентификации / не заботятся о безопасности.Вы можете получить идентификатор соединения signalR в вашем клиенте после подключения через $.connection.hub.id.Затем вы можете отправить этот идентификатор методу сервера в качестве параметра или заголовка.Это никоим образом не должно использоваться в производственной среде, поскольку вы доверяете клиенту, который он есть, и передаете параметры, которые не являются строго необходимыми для вашего метода.

Относительно «почему»:

На самом деле я не думаю, что вам нужен signalR для вашего случая использования.Вы вызываете метод сервера, он сохраняет в БД и возвращает вам ОК или не ОК, клиент доволен.Нет необходимости передавать его через signalR.

Вам нужен signalR, например, когда: - Один и тот же клиент вошел в систему на нескольких устройствах и хочет получать обновления, если были внесены изменения на одном из них - Клиент работает на чем-то, а другой изменяет те же данные.Вы хотите сообщить первому клиенту.- Сообщите вашему клиенту о событии, которое он не инициировал (новое уведомление)

Во всех этих случаях у вас есть какая-то аутентификация, и отправка сообщения signalR нужному клиенту не является проблемой.

Ответ на комментарий ниже

У меня небольшой опыт работы с ajax, думаю, это может сработать.Другая идея, если вы хотите избежать аутентификации, это модель подписки с SignalR.Вы должны выяснить, какие конкретные ресурсы у вас есть, скажем, «игра» в вашем случае, у которых есть идентификаторы.Клиенты, заинтересованные в этом конкретном ресурсе, должны подписаться на изменения.

Все участники конкретного экземпляра карточной игры должны вызвать метод-концентратор, определенный следующим образом:

public async Task SubscribeToGameChanges(long id)
{
    await this.Groups.AddToGroupAsync(this.Context.ConnectionId, Helper.GetGameGroupName(id));
}

public static class Helper{публичная статическая строка GetGameGroupName (long id) {return $ "Game_ {id}";}}

Чем позвонить с клиента.Обратите внимание на AddToGroupAsync.SignalR должен создать группу с заданным именем и добавить в нее клиента.Если группа существует, она просто добавит другого клиента.Таким образом, у вас есть группа для каждого игрового экземпляра со списком заинтересованных клиентов (игроков).

Теперь, когда с игрой происходят изменения, вы уведомляете всех своих клиентов, звоня с вашего контроллера в контексте хаба:

await hubContext.Clients.Groups(Helper.GetGameGroupName(id)).SendAsync("myNotifyMethod", myParameters);

Вы можете упаковать все свои изменения в параметры или просто сообщить клиентам, что состояние игры (или любой другой ресурс) изменилось, и клиенты должны запросить это состояние с помощью обычного вызова API.

Также я заметил, что вы используете GlobalHost в своем коде.Мои примеры кода предназначены для ядра .net версии SignalR и могут немного отличаться в вашем случае.См. здесь о различиях между ядром .net и полным .net SignalR.

...