我正在尝试使用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绑定器)
在事件中执行服务器端代码后,我想调用信号发送器连接以通知客户端。有人可以指导我吗?预先感谢。
答案 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请求管道中映射集线器(如果尚未这样做的话)。
startup.cs
需要注册signalR服务,例如:
startup.cs --> ConfigureServices()
services.AddSignalR();
应该包含您的映射,例如:
startup.cs --> Configure()
如果需要,可以添加更多选项。但是我相信默认值目前已经足够了。
您的中心类可以直接从:Hub继承,以使测试生效。但是要显示一些consol输出,可以覆盖如下所示的虚拟Hub功能:
app.UseSignalR(routes =>
{
routes.MapHub<YourHubClass>("/hub/test1");
routes.MapHub<YourHubClass2>("/hub/test2");
});
根据要在后端代码中何时/何地通知正在监听集线器的所有客户端(或特定客户端),您可以通过执行以下操作简单地发出要传输的数据。
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
现在,您可以连接并收听集线器。例如:
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