Использование SignalR Core для отправки сообщений из метода контроллера в Angular - PullRequest
0 голосов
/ 30 мая 2018

Я пытаюсь использовать SignalR для Asp Net Core 2.1, чтобы отправить сообщение от метода контроллера, вызов которого инициируется с помощью кнопки тестирования в Angular.
Я ожидаю, что при нажатии кнопки моя служба вызывает метод контроллера, который отправляет тестовое сообщение.Затем я просто зарегистрирую сообщение.

Я хочу управлять этим в службе, чтобы избежать дублирования кода во всех компонентах.

Я прочитал несколько примеров, таких как этот вопрос об использовании SignalR в сервисе (я использовал второе решение) и эту статью и официальные документы , но даже с применением этих концепций это не такпохоже на работу.
(Так что, или я совершенно неправильно их применяю, или все еще чего-то не хватает, но я не могу выяснить, что ...)

клиент успешно подключается к Message Hub , и если я нажимаю кнопку, метод получает , но я не получаю никакого сообщения , и вместо этого я получаю это предупреждение вКонсоль Chrome:

Предупреждение. Не найден клиентский метод с именем SendAsync.

Отправка сообщений работает нормально, проблема заключается только в их получении ...

Вопрос: что я делаю не так?Ошибка на внутренней стороне или на угловой стороне?


Я делюсь с вами всем своим кодом (кнопка и служба для вызова метода контроллеране актуально, так как звонок в сервис идет нормально) :

> Startup.cs

public void ConfigureServices(IServiceCollection services)
{
   //...
   services.AddSignalR();
}
//...
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
   //...
   app.UseSignalR(routes =>
   {
      //...
      routes.MapHub<MessageHub>("/messagehub");
      //...
   });
}

> MessageHub.cs

public class MessageHub : Hub<ITypedHubClient>
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

public interface ITypedHubClient
{
    Task SendAsync(string title, string name, string message);
}

> MessageController.cs

IHubContext<MessageHub, ITypedHubClient> _messageHubContext;

public MessageController(IHubContext<MessageHub, ITypedHubClient> messageHubContext)
{
    _messageHubContext = messageHubContext;
}

[HttpPost("Test")]
public async Task<IActionResult> Test()
{
    try
    {
        await _messageHubContext.Clients.All.SendAsync("ReceiveMessage","test", "test");

        return Ok(true);
    }
    catch (Exception e)
    {
        return BadRequest(e);
    }
}

> communication.service.ts

@Injectable()
export class CommunicationService {

  private _hubConnection: HubConnection | undefined;
  public async: any;
  message = '';
  messages: string[] = [];

  private newmessage = new Subject<string>();
  message$ = this.newmessage.asObservable();


  constructor() {
    this._hubConnection = new signalR.HubConnectionBuilder()
      .withUrl('/messagehub')
      //.configureLogging(signalR.LogLevel.Information)
      .configureLogging(signalR.LogLevel.Debug)
      .build();

    this._hubConnection.start().catch(err => console.error(err.toString()));

    this._hubConnection.on('SendMessage', (user: any, message:any) => {
      const received = `Received: ${message}`;
      //this.messages.push(received);
      this.newmessage.next(received);
      console.log("got something new...", received);
    });
  }

  clear() {
    this.newmessage.next("");
  }

  public sendMessage(): void {
    const data = `Sent: ${this.message}`;

    if (this._hubConnection) {
      this._hubConnection.invoke('SendMessage', 'AAA' ,data);
    }
    this.messages.push(data);
  }
}

1 Ответ

0 голосов
/ 31 мая 2018

В ядре сигнализатора 2.1 вы можете использовать строго типизированные концентраторы, чтобы объявить в интерфейсе, какие действия могут быть вызваны на клиентах:

public class MessageHub : Hub<ITypedHubClient>
{
    public async Task SendMessage(string title, string user, string message)
    {
        await Clients.All.SendMessageToClient(title, user, message);
    }
}
public interface ITypedHubClient
{
    Task SendMessageToClient(string title, string name, string message);
}

в контроллере:

    IHubContext<MessageHub, ITypedHubClient> _messageHubContext;

    public async Task<IActionResult> Test()
    {
        await _messageHubContext.Clients.All.SendMessageToClient("test", "test", "test");
        return Ok("ok");
    }

inклиент:

_hubConnection.on('SendMessageToClient', (title, user, message) => {
    const received = `title: ${title}, name: ${user}, message: ${message}`;
    console.log(received);
});

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

public class MessageHub : Hub
{
    public async Task SendMessage(string title, string user, string message)
    {
        await Clients.All.SendAsync("SendMessageToClient", title, user, message);
    }
}

В этом случае вы можете использоватьМетод SendAsync на клиентском прокси, его первым параметром является имя метода, который вы хотите вызвать.

Обновление: когда мы определяем строго типизированный концентратор с интерфейсом, все методы интерфейса должны возвращать задачу.С помощью пользовательских методов, signalr генерирует методы, которые вызывают SendCoreAsync.Это позволяет нам вызывать эти методы асинхронно.

Если тип возвращаемого значения методов интерфейса не является Задачей, мы получаем ошибку: все прокси-методы клиента должны возвращать 'System.Threading.Tasks.Task'

...