调用signalR失败

时间:2019-10-15 06:48:11

标签: angular asp.net-core signalr

我正在尝试使用signalR从.net核心服务器(c#)向我的客户端(角度)发送通知。在事件触发时通知客户端。但是我遇到一个错误。 错误:错误:由于服务器上的错误而无法调用“发送”

Appcomponent.ts

ngOnInit() {
 this._hubConnection = new signalR.HubConnectionBuilder()
.configureLogging(signalR.LogLevel.Information)
.withUrl("http://localhost:5000/message/Send", this.transportType)
.build();
}
form(){
this._hubConnection.on("Send", (data) => {
  const received = `message: ${data}`;
  console.log(received);
  that.disabled = false;
});
  this._hubConnection.start()
.then(() =>
this._hubConnection.invoke('Send', "hey")
.catch(function (err) {
 console.error(err.toString());
})
)
.then(() =>
console.log('connected'))
.then(() => this._hubConnection.stop())
.then(() => console.log('Disconnected'))
.catch(e => console.error(e.message));
}

SignalR集线器

public class DataHub : Hub
{
    public async Task Send1(string message1, string Root)
    {
        await Clients.All.SendAsync("Send1", message1);
    }
}

控制器

public class DataController : Controller
{
    private IHubContext<DrawingHub> _hubContext;
    public DataController(IHubContext<DataHub> hubContext)
    {
        _hubContext = hubContext;
    }
    private void OnProvideData(DataAndHeader data)
    {
        // server side code
        _hubContext.Clients.All.SendAsync("Send", data);
    }
}

Startup.cs

services.AddSignalR();

app.UseSignalR(routes =>
            {
                routes.MapHub<DrawingHub>("/message/Send");
            });

错误记录

  

失败:Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher [8]         无法调用集线器方法“发送”。   System.IO.InvalidDataException:调用提供1个参数,但目标期望0。      在Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.BindArguments(JArray args,IReadOnlyList`1 paramTypes)      在Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.ParseMessage(Utf8BufferTextReader textReader,IInvocationBinder绑定器)

在事件中执行服务器端代码后,我想调用信号发送器连接以通知客户端。有人可以指导我吗?预先感谢。

2 个答案:

答案 0 :(得分:0)

您在客户端上调用的方法名称必须与SignalR Hub中的名称相同(但也允许使用小写方法)。

由于您的Hub方法被称为Send1,而您的客户调用了Send,因此找不到该方法。要解决此问题,您可以将Hub方法重命名为Send或将客户端代码更改为调用this._hubConnection.invoke('send1', "hey", "ho")

这是您的工作:

  • this._hubConnection.on("Send", ...让客户端监听名为Send的服务器事件。

  • this._hubConnection.invoke('Send', "hey")调用名为Send的服务器方法。这不存在!服务器方法称为Send1

  • public async Task Send1( string message1, string Root)声明一个名为Send1的方法。

  • 在客户端中,您尝试调用Send1的任何地方,而仅调用Send(无1)。
  • await Clients.All.SendAsync("Send1", message1);,如果将调用Send1,则您将尝试向所有客户端发布Send1消息。不过,没有客户在听Send1,只有Send在听。

现在查看您的错误消息:Failed to invoke hub method 'Send'.正在寻找集线器方法Send,但它不存在,因为您改名为Send1

快速修复:只需将所有出现的Send1重命名为Send。因为这就是您要在客户端上调用的内容。此外,由于hub方法有2个参数,因此还必须使用2个参数(而不是当前的参数)来调用它。

答案 1 :(得分:0)

Cordova中,应该注册signalR服务并在http请求管道中映射集线器(如果尚未这样做的话)。

步骤1

startup.cs需要注册signalR服务,例如:

   
startup.cs --> ConfigureServices()

services.AddSignalR(); 应该包含您的映射,例如:

   
startup.cs --> Configure()

如果需要,可以添加更多选项。但是我相信默认值目前已经足够了。

步骤2

您的中心类可以直接从:Hub继承,以使测试生效。但是要显示一些consol输出,可以覆盖如下所示的虚拟Hub功能:

   
app.UseSignalR(routes =>
{
   routes.MapHub<YourHubClass>("/hub/test1");
   routes.MapHub<YourHubClass2>("/hub/test2");
});

步骤3

根据要在后端代码中何时/何地通知正在监听集线器的所有客户端(或特定客户端),您可以通过执行以下操作简单地发出要传输的数据。

   
public class YourHubClass: Hub
{
    public override async Task OnConnectedAsync()
    {
        Console.WriteLine(Context.ConnectionId);
        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception ex)
    {
        Console.WriteLine(Context.ConnectionId);            
        await base.OnDisconnectedAsync(ex);
    }
}

在此范围内,var test1data = GetTest1Data(); await _hub.Clients.All.SendAsync("test1", test1data); var test2data = GetTest1Data(); await _hub.Clients.All.SendAsync("test2", test2data); 是依赖项注入的地方。只是要澄清一下:

   
_hub

步骤4

现在,您可以连接并收听集线器。例如:

 
private readonly IHubContext<YourHubClass> _hub;

public YourScopedConstructor(IHubContext<YourHubClass> hub) 
{
    _hub = hub ?? throw new ArgumentNullException(nameof(hub));
}

要让其他任何组件获取数据,只需订阅public yourSubscribableSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null); private _baseUrl: string = "your base url"; private _frontendHubConnection: HubConnection; this._frontendHubConnection = new HubConnectionBuilder() .withUrl(`${this._baseUrl}/hub/test1`) // or hub/test2 .configureLogging(LogLevel.Information) .build(); this._frontendHubConnection .start() .then(() => console.log('SignalR - init')) .catch(err => console.log('Error while starting connection: ' + err)); this._frontendHubConnection.on('test1', (data: any) => { console.log(data); this.yourSubscribableSubject.next(data); }); 。希望它会有所帮助。

此外,如果您想触发数据从API端点从服务器发送到客户端,只需移动我在步骤3中建议的作用域代码即可。

   
yourSubscribableSubject