使用 SignalR Core 将消息从控制器方法发送到 Angular



我正在尝试将SignalR用于Asp Net Core 2.1,以便从控制器方法发送消息,该消息从Angular中的测试按钮触发调用。
我期望的行为是,当我单击该按钮时,我的服务会调用控制器方法,该方法会发送测试消息。然后,我将简单地记录消息。

我想在服务中管理它,以避免所有组件中的代码重复。

我已经阅读了一些示例,例如有关在服务中使用 SignalR 的问题(我使用了第二种解决方案(以及本文和官方文档,但即使应用这些概念,它似乎也不起作用。
(所以,或者我绝对以错误的方式应用它们,或者仍然缺少一些东西,但我找不到什么......

客户端成功连接到消息中心,如果我单击该按钮,该方法将受到攻击,但我没有收到任何消息,而是在Chrome控制台中收到以下警告:

警告:未找到名称为"SendAsync"的客户端方法。

发送消息工作正常,问题只是接收它们...

问题是:我做错了什么?错误是在后端还是在角度端?


与您分享我的所有代码(按钮和调用控制器方法的服务无关紧要,因为对服务的调用正常(

>启动.cs

public void ConfigureServices(IServiceCollection services)
{
//...
services.AddSignalR();
}
//...
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//...
app.UseSignalR(routes =>
{
//...
routes.MapHub<MessageHub>("/messagehub");
//...
});
}

>消息中心.cs

public class MessageHub : Hub<ITypedHubClient>
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
public interface ITypedHubClient
{
Task SendAsync(string title, string name, string message);
}

>消息控制器.cs

IHubContext<MessageHub, ITypedHubClient> _messageHubContext;
public MessageController(IHubContext<MessageHub, ITypedHubClient> messageHubContext)
{
_messageHubContext = messageHubContext;
}
[HttpPost("Test")]
public async Task<IActionResult> Test()
{
try
{
await _messageHubContext.Clients.All.SendAsync("ReceiveMessage","test", "test");
return Ok(true);
}
catch (Exception e)
{
return BadRequest(e);
}
}

>通信服务.ts

@Injectable()
export class CommunicationService {
private _hubConnection: HubConnection | undefined;
public async: any;
message = '';
messages: string[] = [];
private newmessage = new Subject<string>();
message$ = this.newmessage.asObservable();

constructor() {
this._hubConnection = new signalR.HubConnectionBuilder()
.withUrl('/messagehub')
//.configureLogging(signalR.LogLevel.Information)
.configureLogging(signalR.LogLevel.Debug)
.build();
this._hubConnection.start().catch(err => console.error(err.toString()));
this._hubConnection.on('SendMessage', (user: any, message:any) => {
const received = `Received: ${message}`;
//this.messages.push(received);
this.newmessage.next(received);
console.log("got something new...", received);
});
}
clear() {
this.newmessage.next("");
}
public sendMessage(): void {
const data = `Sent: ${this.message}`;
if (this._hubConnection) {
this._hubConnection.invoke('SendMessage', 'AAA' ,data);
}
this.messages.push(data);
}
}

在 signalr core 2.1 中,您可以使用强类型集线器在接口中声明可以在客户端上调用哪些操作:

public class MessageHub : Hub<ITypedHubClient>
{
public async Task SendMessage(string title, string user, string message)
{
await Clients.All.SendMessageToClient(title, user, message);
}
}
public interface ITypedHubClient
{
Task SendMessageToClient(string title, string name, string message);
}

在控制器中:

IHubContext<MessageHub, ITypedHubClient> _messageHubContext;
public async Task<IActionResult> Test()
{
await _messageHubContext.Clients.All.SendMessageToClient("test", "test", "test");
return Ok("ok");
}

在客户端中:

_hubConnection.on('SendMessageToClient', (title, user, message) => {
const received = `title: ${title}, name: ${user}, message: ${message}`;
console.log(received);
});

如果不使用强类型集线器,则在客户端中调用相同的方法,它将变为:

public class MessageHub : Hub
{
public async Task SendMessage(string title, string user, string message)
{
await Clients.All.SendAsync("SendMessageToClient", title, user, message);
}
}

在这种情况下,您可以在客户端代理上使用 SendAsync 方法,它的第一个参数是要调用的方法的名称。

更新: 当我们定义一个带有接口的强类型集线器时,所有接口方法都必须返回一个 Task。使用自定义方法,信号器生成调用 SendCoreAsync 的方法。这允许我们异步调用这些方法。

如果接口方法的返回类型不是任务,我们会收到错误:所有客户端代理方法都必须返回"System.Threading.Tasks.Task">

最新更新