Как подключить SignalR к приложению Angular 7 - PullRequest
0 голосов
/ 21 января 2019

Я просто не могу понять, как установить соединение сигнализатора с Angular.

Используя следующий учебник на https://docs.microsoft.com/en-us/aspnet/signalr/overview/getting-started/tutorial-getting-started-with-signalr-and-mvc

Я добавил новый проект SignalR 2.4.0 в существующее решение .Net 4.6 в vs2017.

У меня также есть приложение Angular 7, в которое я добавил пакет SignalR через npm install @aspnet/signalr

Сейчас я пытаюсь установить простое соединение между клиентом и сервером, но не могу понять, как установить первоначальное соединение.

Мой клиент продолжает выдавать исключение:

 core.js:15714 ERROR Error: Uncaught (in promise): Error: Cannot send data if the connection is not in the 'Connected' State.

Ошибка: невозможно отправить данные, если соединение не находится в состоянии «Подключено».

В моем компоненте поиска переднего плана я добавил несколько полей для тестирования:

<mat-form-field>
    <input matInput placeholder="message" [(ngModel)]="message">
</mat-form-field>
<button mat-button type="button" (click)="sendMessageToServer()"><span>Send</span></button>            
<p *ngFor="let m of messages">{{m}}</p>

И в моем файле ts:

// import other components/services here..
import { HubConnection, HubConnectionBuilder} from '@aspnet/signalr';

@Component({
  selector: 'app-my-search',
  templateUrl: './my-search.component.html',
  styleUrls: ['./my-search.component.scss']
})
export class MySearchComponent implements OnInit {

public hubConnection: HubConnection;
  public messages: string[] = [];
  public message: string;

   constructor() { }
   
   
  ngOnInit() {
   
    // SIGNALR MESSAGE HUB
    let builder = new HubConnectionBuilder();
    this.hubConnection = builder.withUrl('/SynBroadcastHub/BroadcastMessage').build();  // see startup.cs
    this.hubConnection.on('notifyUser', (message) => {
      this.messages.push(message);
      console.log(message);
    });
    this.hubConnection.start();
  }

  // signalr, send msg from client
  sendMessageToServer() {
    this.hubConnection.invoke('MessageToServer', this.message);
    this.message = '';
  }


}

и на стороне c # я добавил SignalR Hub Class (v2) файл BroadcastHub.cs

using Microsoft.AspNet.SignalR;

namespace SynBroadcastHub
{
    public class BroadcastHub : Hub
    {        
        /// Message to client 
        public void BroadcastMessage(string data)
        {
            Clients.Caller.notifyUser(data);
        }
    
        
        /// Message from client application; broadcast to all clients if requested.                
        public void MessageToServer(string data, bool notifyAllClients = false)
        {
            if (notifyAllClients)
            {
                Clients.All.NotifyAllClients(data);
            }
        }
    }
}

, а также Startup.cs файл:

using Microsoft.Owin;
using Microsoft.AspNet.SignalR;
using Owin;

[assembly: OwinStartup(typeof(SynBroadcastHub.Startup))]

namespace SynBroadcastHub
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            HubConfiguration cfg = new HubConfiguration();
            app.MapSignalR<PersistentConnection>("BroadcastHub/BroadcastMessage");
            app.MapSignalR(cfg);
            app.MapSignalR();

            //app.MapSignalR<NotifyHub>("notify"); ???
        }
         public override Task OnDisconnected(bool stopCalled)
        {
            return Clients.All.leave(Context.ConnectionId, System.DateTime.Now.ToString());
        }

        public override Task OnConnected()
        {
            return Clients.All.joined(Context.ConnectionId, DateTime.Now.ToString());
        }

        public override Task OnReconnected()
        {
            return Clients.All.rejoined(Context.ConnectionId, DateTime.Now.ToString());
        }
    }
}

Ответы [ 3 ]

0 голосов
/ 04 февраля 2019

Вы уверены, что точка hubEndpoint верна? Кажется, что концентратор является частью угловой маршрутизации (судя по тому, как вы пишете). Попробуйте установить полный путь (например, https://www.myapp.com/SynBroadcastHub/BroadcastMessage)

0 голосов
/ 07 марта 2019

Я просто потратил два дня, пытаясь понять то же самое. Я наконец заставил его работать, и вот несколько вещей, которые мне пришлось сделать:

1) Вы заметили, что использование пакета @aspnet/signalr было некорректно для .Net framework, и это правильно. Вам нужен пакет signalr (npm install signalr).

2) Это самая важная часть всего процесса. SignalR зависит от jQuery. У вас есть для включения jQuery до , включая скрипт-сигнализатор. В файле angular.json в разделе scripts необходимо указать:

"./node_modules/jquery/dist/jquery.js", "./node_modules/signalr/jquery.signalR.js"

в этом точном порядке. При запуске вашего проекта он сначала загрузит jQuery, а затем скрипт signalR.

Многие другие потоки стековых ответов отвечают на вопрос в ответ на эту ошибку:

jQuery was not found. Please ensure jQuery is referenced before the SignalR client JavaScript file

говорит вам написать import * as $ from "jquery" в компоненте, в котором вы хотите использовать jQuery. Однако, НЕ правильно сделать это. Причина в том, что согласно этой угловой статье о глобальных сценариях , использование синтаксиса import включит его в нагрузку module и поместит в файл vendor.js, созданный при запуске ng build команда. Причина в том, что проблема заключается в том, что сначала jQuery будет загружен из вашего angular.json, затем будет загружен signalR, затем модуль из vendor.js перезапустит jQuery и отсоединит все события, которые были только что присоединены к jQuery из signalR.

3) Поскольку вы заметили, что используете версию сигнализатора .Net Core, у вас не будет доступа к HubConnectionBuilder при попытке создания нового HubConnection в вашем угловом компоненте.

Вместо этого, когда исполняется скрипт сигнализатора, он присоединяет дополнительные события к $ в вашем коде. Примечание: если вы получаете ошибки при сборке или во время компиляции из ваших файлов ts, убедитесь, что вы включили @types/signalr и @types/jquery из npm

Чтобы установить новое соединение с концентратором, используйте $.hubConnection("your-url-here/signalr"). Он будет подключен к концентратору вашего сервера при запуске. Примечание: Я сохранил результат этого как переменную с именем hubConnection в моем угловом компоненте

В коде вашего сервера (файл .cs), где у вас есть класс Hub, вам нужно будет добавить над именем класса: [HubName("YourHubName")]. Так что в вашем случае ваш файл .cs будет выглядеть примерно так:

[HubName("Broadcast")]    
public class BroadcastHub : Hub

Скорее всего, вам придется включить это в начало вашего файла .cs: using Microsoft.AspNet.SignalR.Hubs;

Затем в вашем Angular Component вы настраиваете прокси для подключения к этому хабу на вашем сервере. В следующей строке после создания нового hubConnection напишите:

this.hubConnection.createHubProxy("yourHubName");.

В вашем случае this.hubConnection.createHubProxy("broadcast");

После того, как вы создали свой прокси, вы можете присоединить слушателей для прослушивания событий, исходящих от сервера, или вы можете вызывать функции сервера из ваших угловых компонентов.

Я следовал этому примеру здесь, чтобы узнать, как настроить вызовы и прослушивание событий сервера. Да, это angular 2, но функции из signalr все еще работают одинаково в моем приложении angular 7.

Краткий ответ: используйте от proxy.on('eventname') до прослушивания событий с сервера и используйте функции proxy.invoke('eventname') до вызова на вашем хабе из ваших угловых компонентов.

Наконец, несколько заметок в ваших файлах cs. В моем Startup.cs единственное, что у меня есть для отображения сигнализатора, это app.MapSignalR(). Я не стал вдаваться в подробности, касающиеся установки других свойств, как вы сделали, но это может быть еще одной причиной некоторых проблем?

0 голосов
/ 23 января 2019

Я сам исследовал эту тему и нашел пакет npm ng2-signal. Может быть, что-то посмотреть на себя?

...