Я работаю над подключением 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
. Мой вчерашний вопрос.
РЕДАКТИРОВАТЬ
Ввод 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"));
}
РЕДАКТИРОВАТЬ2
Вот соединение, которое я могу получить, когда мой клиент WPF
зарегистрирует свое соединение:
@TanvirArjel я тоже добавил Startup.cs
(только с signalR). Загляни в мою правку
Что я знаю, когда у меня есть что-то вроде static Instance
с { get; } = New
, это должно работать как синглтон, в этом случае я хотел добиться постоянного Hub
получения сообщений от Webapi
, когда кто-то вызывает Post
действие
Я пробовал ваш код со всеми типами клиентов (wpf/консоль/даже с браузером), он всегда работает нормально для меня. hubConnection.On<string>("ReciveServerUpdate", update => {//todo});
всегда вызывается, когда я отправляю запрос на PostTask
. Есть ли минимальная демо, которая воспроизводит?
Потому что... это работает! Я просто не знал, что во время отладки я не могу получить доступ к методу hub.On
... Итак, мне нужно закрыть этот вопрос или просто оставить его следующим поколениям? Вы правы @itminus. Я просто потерял много времени, пытаясь отладить его.
:) Это действительно вопрос Шредингера .... Я считаю, что если вы не можете воспроизвести ту же проблему, лучше обновить свой вопрос, чтобы напомнить кому-то, кто хочет провести расследование. Но не удаляйте этот вопрос, если это ошибка, которую мы пока не заметили.
Я считаю, вы можете опубликовать ответ. Я отмечу это, потому что это помогает tbh
Не могли бы вы сказать мне, что ваш экземпляр отладчика VS попадает в hubConnnection.On
? Потому что я заполнил Notifications
updates
из этого метода, и отладчик, когда я разместил задачу, не активировал мою точку останова, но список Notifications
был заполнен
@michasaucer Да. Точка останова срабатывает как в VS, так и в VSCode.
@michasaucer Когда вы говорите «не сработала моя точка останова», как вы настраиваете аргументы обработчика? Количество аргументов должно быть одинаковым.
Я только что установил точку останова в hubConnection.On
, и она никогда не срабатывает. Когда я просто проверял, что в Notifications
, были сообщения от Webapi
, отправленные хабом
Давайте продолжить обсуждение в чате.
@michasaucer Вы перезапускали клиент при отладке?
@itminus спасибо, что потратили свое время. Пожалуйста, напишите ответ, чтобы я пометил его как решение моей проблемы.
Я пробовал ваш код со всеми типами клиентов (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();
Пожалуйста, укажите, что мой код работает в вашем ответе для следующего поколения разработчиков .NET (некоторые из них сразу погружаются в ответы)
Покажите код, как вы внедрили
NotificationsHub
в свой контроллер.