我正在处理SignalR Clinet-Server连接。我的服务器是WebApi Core 2.1
,我的客户是WPF .NET Framework 4.7.2
。
在客户端,我有一个singleton
集线器服务,其中有一个实例来接收来自服务器的消息:
using System.Collections.ObjectModel;
using Microsoft.AspNetCore.SignalR.Client;
public class HubService
{
//singleton
public static HubService Instance { get; } = new HubService();
public ObservableCollection<string> Notifications { get; set; }
public async void Initialize()
{
this.Notifications = new ObservableCollection<string>();
var hubConnection = new HubConnectionBuilder()
.WithUrl(UrlBuilder.BuildEndpoint("Notifications"))
.Build();
hubConnection.On<string>("ReciveServerUpdate", update =>
{
//todo
});
await hubConnection.StartAsync();
}
}
我将其初始化为单例:
public MainWindowViewModel()
{
HubService.Instance.Initialize();
}
我正在调试时,在MainWindowViewModel
上碰到了HubService
。
在Server
端,它看起来像这样。
Hub
:
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
public class NotificationsHub : Hub
{
public async Task GetUpdateForServer(string call)
{
await this.Clients.Caller.SendAsync("ReciveServerUpdate", call);
}
}
我通过控制器的方法触发发送消息:
[HttpPost]
public async Task<IActionResult> PostTask([FromBody] Task task)
{
if (!this.ModelState.IsValid)
{
return this.BadRequest(this.ModelState);
}
this.taskService.Add(task);
//here im calling sending message. When im debugging
//i see one connection from my WPF with unique ConnectionId
await this.notificationsHub.Clients.All.SendAsync("ReciveServerUpdate", "New Task in database!");
return this.Ok(task);
}
正如我之前所写,在调试WebApi
时,在Clients
中,我与WPF
之间只有一个连接。当我关闭WPF
时,connection count = 0
可以使连接正常工作。
但是当我打电话给SendAsync()
时,我没有收到WPF
中hubConnection.On
中的任何信息。有趣的是,昨天它运行良好。
因此,我考虑将HubService
设置为静态singleton
是正确的吗?如果是这样,为什么当我的WebApi
连接到SignalR
时,我无法从WPF
接收消息?
昨天我问过类似的问题,但是找到了解决方案。昨天,我的方法有效,当我收到hubConnection.On
的任何消息时,我可以打WebApi
。 My question from yestarday。
编辑
向控制器注入HUb
:
private readonly ITaskService taskService;
private readonly IHubContext<NotificationsHub> notificationsHub;
public TaskController(ITaskService taskService, IHubContext<NotificationsHub> notificationsHub)
{
this.taskService = taskService;
this.notificationsHub = notificationsHub;
}
仅Startup.cs
个SignalR
事物(我删除了与信号无关的其他事物):
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddSignalR();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseSignalR(routes => routes.MapHub<NotificationsHub>("/Notifications"));
}
EDIT2
当我的客户WPF
将注册他的连接时,这是我可以获得的连接:
答案 0 :(得分:1)
我在各种客户端(wpf / console /甚至使用浏览器)上尝试了您的代码,对于我来说,它始终可以正常工作。当我向hubConnection.On<string>("ReciveServerUpdate", update => {//todo});
发送请求时,总是会调用PostTask
。
我不确定为什么(有时)对您不起作用。但是,当SignalR客户端已连接到服务器但没有收到来自服务器的消息时,可能有两个原因:
PostTask([FromBody] Task task)
操作方法未执行。假设这是一个ApiController
方法,如果浏览器偶然发布了Content-Type
为application/www-x-form-urlencoded
的请求,则根本不会执行Clients.All.SendAsync(..., ...);
的调用。 SigalR客户端(hubConnection.On<>(method,handler)
)的处理程序必须具有与调用完全相同的参数列表,才能接收消息。在处理此问题时,我们必须非常小心。
最后,最好添加对Microsoft.Extensions.Logging.Console
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.2.*" />
以便我们可以启用日志记录以进行故障排除:
var hubConnection = new HubConnectionBuilder()
.WithUrl(UrlBuilder.BuildEndpoint("Notifications"))
.ConfigureLogging(logging =>{
logging.AddConsole(); // enable logging
})
.Build();