我期望的行为是当我单击按钮时,我的服务调用控制器方法,该方法发送测试消息.然后,我将简单地记录消息.
我想在服务中管理它,以避免所有组件中的代码重复.
我已经阅读了一些例子,如this question about using SignalR in a service(我已经使用了第二个解决方案)和this article和the official docs,但即使应用这些概念,它似乎也不起作用. (所以,或者我绝对是以错误的方式应用它们,或者仍然缺少某些东西,但我找不到…
客户端成功连接到消息中心,如果我单击该按钮,该方法将被点击但我没有收到任何消息,而是在Chrome控制台中收到此警告:
Warning: No client method with the name ‘SendAsync’ found.
发送消息很好,问题就在于接收它们……
问题是:我做错了什么?是后端还是Angular端的错误?
我与你分享我的所有代码(调用控制器方法的按钮和服务是不相关的,因为对服务的调用很顺利):
> Startup.cs
public void ConfigureServices(IServiceCollection services) { //... services.AddSignalR(); } //... public void Configure(IApplicationBuilder app,IHostingEnvironment env) { //... app.UseSignalR(routes => { //... routes.MapHub<MessageHub>("/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); }
> MessageController.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); } }
> communication.service.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); } }
解决方法
public class MessageHub : Hub<ITypedHubClient> { public async Task SendMessage(string title,string user,string message) { await Clients.All.SendMessagetoClient(title,message); } } public interface ITypedHubClient { Task SendMessagetoClient(string title,string message); }
在控制器中:
IHubContext<MessageHub,ITypedHubClient> _messageHubContext; public async Task<IActionResult> test() { await _messageHubContext.Clients.All.SendMessagetoClient("test","test"); return Ok("ok"); }
在客户端:
_hubConnection.on('SendMessagetoClient',(title,message) => { const received = `title: ${title},name: ${user},message: ${message}`; console.log(received); });
如果你不使用强类型集线器,那么在客户端调用相同的方法它变成:
public class MessageHub : Hub { public async Task SendMessage(string title,string message) { await Clients.All.SendAsync("SendMessagetoClient",title,message); } }
在这种情况下,您可以在客户端代理上使用SendAsync方法,它的第一个参数是您要调用的方法的名称.
更新:
当我们使用接口定义强类型集线器时,所有接口方法都必须返回一个Task.使用自定义方法,signalr生成调用SendCoreAsync的方法.这允许我们异步调用这些方法.
如果接口方法的返回类型不是Task,我们会收到错误:所有客户端代理方法都必须返回’System.Threading.Tasks.Task’
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。