如何使用Angular 7应用程序连接SignalR

bob*_*zzo 8 c# signalr signalr-2 angular

我根本无法弄清楚如何从Angular建立信号发送器连接。

https://docs.microsoft.com/zh-cn/aspnet/signalr/overview/getting-started/tutorial-getting-started-with-signalr-and-mvc使用以下教程

SignalR在vs2017中为现有的.Net 4.6解决方案添加了一个新的2.4.0项目。

我也有一个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.
Run Code Online (Sandbox Code Playgroud)

错误:如果连接未处于“已连接”状态,则无法发送数据。

在前端搜索组件中,我添加了一些测试字段:

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

在我的ts文件中:

<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>
Run Code Online (Sandbox Code Playgroud)

在C#端,我添加了一个SignalR Hub Class (v2)文件BroadcastHub.cs

// 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 = '';
  }


}
Run Code Online (Sandbox Code Playgroud)

以及Startup.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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

pol*_*pol 17

我只花了两天时间试图弄清楚这件事。我终于让它工作了,这些是我要做的几件事:

1)您注意到使用该@aspnet/signalr软件包对于.Net framework不正确,这是正确的。您需要signalr包装(npm install signalr)。

2)这是整个过程中最关键的部分。SignalR有依赖jQuery包含Signalr脚本之前,必须包含jQuery 。在该部分下的文件中,您需要包括:angular.jsonscripts

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

按照确切的顺序。在您的项目启动时,它将首先加载jQuery,然后加载signalR脚本。

许多其他stackover流回答了该问题,以回答此错误:

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并从signalR取消附加刚刚附加到jQuery的所有事件。

3)由于您注意到自己使用的是.Net Core版本的signalr,因此HubConnectionBuilder在实例化角度组件中的新HubConnection时将无法访问。

相反,当signalr脚本执行后,它将$在代码中附加其他事件。注意:如果您从ts文件中在构建或编译时遇到错误,请确保已在npm中包含@types/signalr@types/jquery

要建立新的集线器连接,请使用$.hubConnection("your-url-here/signalr")。运行时,它将连接到服务器的集线器。注意:我将由此产生的结果存储为hubConnection我的角度组件中调用的变量

在具有Hub类的服务器代码(.cs文件)上,需要在类名称上方添加 [HubName("YourHubName")]。因此,在您的情况下,您的.cs文件在顶部看起来像这样:

[HubName("Broadcast")]    
public class BroadcastHub : Hub
Run Code Online (Sandbox Code Playgroud)

您很可能必须在.cs文件的顶部包含以下内容: using Microsoft.AspNet.SignalR.Hubs;

然后在Angular Component中设置一个代理以附加到服务器上的该Hub实例化新的hubConnection之后的下一行,编写:

this.hubConnection.createHubProxy("yourHubName");

就你而言 this.hubConnection.createHubProxy("broadcast");

制作代理后,您可以附加侦听器以侦听服务器发出的事件,或者可以从角度组件调用服务器功能。

我在这里按照此示例学习了如何设置调用事件和侦听服务器事件。是的,它是角度2,但是在我的角度7应用程序中,信号器的所有功能仍然相同。

简短的回答:使用proxy.on('eventname')收听到来自服务器的事件,并使用proxy.invoke('eventname')调用从您的角度分量上的枢纽功能。

最后,您的cs文件中有一些注意事项。在我的Startup.cs中,我唯一需要映射signalr的东西app.MapSignalR()。我没有像您一样详细设置其他属性,但这可能是引起某些问题的另一个原因?

  • 这真的很有帮助。感谢您花时间写下此内容 (5认同)

Wie*_*tze 1

我自己刚刚研究这个主题,发现了 npm 包 ng2-signal。也许需要审视一下自己?