无法调用 signalR
Failed to invoke signalR
我正在尝试使用 signalR 从 .net 核心服务器 (c#) 向我的客户端 (Angular) 发送通知。在触发事件时通知客户端。但我收到一个错误。
错误:错误:由于服务器
上的错误,无法调用 'Send'
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");
});
错误记录
fail: Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher[8]
Failed to invoke hub method 'Send'.
System.IO.InvalidDataException: Invocation provides 1 argument(s) but target expects 0.
at Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.BindArguments(JArray args, IReadOnlyList`1 paramTypes)
at Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.ParseMessage(Utf8BufferTextReader textReader, IInvocationBinder binder)
我想在事件中执行服务器端代码后调用signalr连接来通知客户端。有人可以指导我吗?提前致谢。
您在客户端调用的方法名称必须与您的 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
。因为这就是您要在客户端上调用的内容。此外,您还必须使用 2 个参数调用它,而不是像现在这样的参数,因为 hub 方法有 2 个参数。
在您的 startup.cs
中,您应该注册 signalR 服务并在 http 请求管道中映射您的集线器,如果您还没有这样做的话。
步骤 1
startup.cs --> ConfigureServices()
需要注册signalR服务,例如:
services.AddSignalR();
startup.cs --> Configure()
应包含您的映射,例如:
app.UseSignalR(routes =>
{
routes.MapHub<YourHubClass>("/hub/test1");
routes.MapHub<YourHubClass2>("/hub/test2");
});
如果需要,可以添加更多选项。但我相信默认值现在已经足够好了。
第 2 步
您的集线器 class 可以简单地继承自 : Hub 以进行测试。但是要显示一些控制台输出,您可以像这样覆盖虚拟 Hub 函数:
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);
}
}
步骤 3
根据您后端代码中的 when/where,您想要通知正在收听您的集线器的所有客户端(或特定客户端),您可以通过执行类似的操作来简单地发出您想要传输的数据这个。
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));
}
第 4 步
现在您可以连接并收听集线器了。例如:
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);
});
而要获取数据的任何其他组件,只需订阅 yourSubscribableSubject
。希望对您有所帮助。
另外,如果你想触发数据从服务器从 API 端点发送到客户端,只需移动我在步骤 3 中建议的作用域代码。
public async Task<ActionResult> YourApiRoute()
{
try
{
var test1data = GetTest1Data();
await _hub.Clients.All.SendAsync("test1", test1data);
return Ok();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
我正在尝试使用 signalR 从 .net 核心服务器 (c#) 向我的客户端 (Angular) 发送通知。在触发事件时通知客户端。但我收到一个错误。 错误:错误:由于服务器
上的错误,无法调用 'Send'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");
});
错误记录
fail: Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher[8] Failed to invoke hub method 'Send'. System.IO.InvalidDataException: Invocation provides 1 argument(s) but target expects 0. at Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.BindArguments(JArray args, IReadOnlyList`1 paramTypes) at Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.ParseMessage(Utf8BufferTextReader textReader, IInvocationBinder binder)
我想在事件中执行服务器端代码后调用signalr连接来通知客户端。有人可以指导我吗?提前致谢。
您在客户端调用的方法名称必须与您的 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
。因为这就是您要在客户端上调用的内容。此外,您还必须使用 2 个参数调用它,而不是像现在这样的参数,因为 hub 方法有 2 个参数。
在您的 startup.cs
中,您应该注册 signalR 服务并在 http 请求管道中映射您的集线器,如果您还没有这样做的话。
步骤 1
startup.cs --> ConfigureServices()
需要注册signalR服务,例如:
services.AddSignalR();
startup.cs --> Configure()
应包含您的映射,例如:
app.UseSignalR(routes =>
{
routes.MapHub<YourHubClass>("/hub/test1");
routes.MapHub<YourHubClass2>("/hub/test2");
});
如果需要,可以添加更多选项。但我相信默认值现在已经足够好了。
第 2 步
您的集线器 class 可以简单地继承自 : Hub 以进行测试。但是要显示一些控制台输出,您可以像这样覆盖虚拟 Hub 函数:
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);
}
}
步骤 3
根据您后端代码中的 when/where,您想要通知正在收听您的集线器的所有客户端(或特定客户端),您可以通过执行类似的操作来简单地发出您想要传输的数据这个。
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));
}
第 4 步
现在您可以连接并收听集线器了。例如:
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);
});
而要获取数据的任何其他组件,只需订阅 yourSubscribableSubject
。希望对您有所帮助。
另外,如果你想触发数据从服务器从 API 端点发送到客户端,只需移动我在步骤 3 中建议的作用域代码。
public async Task<ActionResult> YourApiRoute()
{
try
{
var test1data = GetTest1Data();
await _hub.Clients.All.SendAsync("test1", test1data);
return Ok();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}