Не удалось вызвать signalR - PullRequest
0 голосов
/ 15 октября 2019

Я пытаюсь отправить уведомление Моему клиенту (Angular) с главного сервера .net (c #) с помощью signalR. уведомить клиента, когда событие происходит. Но я получаю ошибку. Ошибка: Ошибка: не удалось вызвать «Отправить» из-за ошибки на сервере

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");
            });

Ведение журнала ошибок

ошибка: Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher [8] Не удалось вызвать метод-концентратор «Отправить»». System.IO.InvalidDataException: Вызов предоставляет 1 аргумент (ов), но цель ожидает 0. в Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol.BindArguments (аргументы JArray, IReadOnlyList`1 paramTypes) в Microsoft.AspNetCore.SignalR.Protocol.son. ParseMessage (Utf8BufferTextReader textReader, IInvocationBinder binder)

Я хочу вызвать соединение сигнализатора для уведомления клиента после выполнения кода стороны сервера в событии. Может кто-нибудь, пожалуйста, направьте меня. Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 15 октября 2019

В вашем 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

Ваш класс-концентратор может просто наследоваться от: 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

В зависимости от того, когда / где в вашем внутреннем коде вы хотите уведомить всех клиентов(или определенных клиентов), которые слушают ваш концентратор, вы можете просто передать данные, которые вы хотите передать, выполнив что-то вроде этого.

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);
    }
 }
0 голосов
/ 15 октября 2019

Имя метода, которое вы вызываете на клиенте, должно быть таким же, как в вашем SignalR Hub (за исключением того, что строчные методы также допускаются).

Поскольку ваш метод Hub называется Send1 и ваш клиентзвонит Send, метод не найден. Чтобы решить эту проблему, вы можете переименовать ваш метод-концентратор на 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 аргумента, а не один, как в настоящее время, так как метод концентратора имеет 2 параметра.

...