Не найден клиентский метод с именем 'x' с SignalR - PullRequest
0 голосов
/ 05 июля 2018

У меня есть проект ASP.NET Boilerplate v3.6.2 (.NET Core / Angular), в котором мне нужно вызвать клиентскую функцию из внутреннего метода, поэтому я использую реализацию ASP.NET Core SignalR .

Я следовал официальной документации, поэтому:

В бэкэнде

  1. В моем модуле я добавил зависимость к AbpAspNetCoreSignalRModule:

    [DependsOn(typeof(AbpAspNetCoreSignalRModule))]
    public class MyModule : AbpModule
    

    И добавил этот пакет NuGet в проект модуля.

  2. Затем я расширил класс AbpCommonHub, чтобы воспользоваться встроенной реализацией SignalR Hub, добавив метод SendMessage(), используемый для отправки сообщения:

    public interface IMySignalRHub :  ITransientDependency
    {
        Task SendMessage(string message);
    }
    
    public class MySignalRHub: AbpCommonHub, IMySignalRHub {
        protected IHubContext<MySignalRHub> _context;
        protected IOnlineClientManager onlineClientManager;
        protected IClientInfoProvider clientInfoProvider;
    
        public MySignalRHub(
            IHubContext<MySignalRHub> context, 
            IOnlineClientManager onlineClientManager,
            IClientInfoProvider clientInfoProvider)
        : base(onlineClientManager, clientInfoProvider) {
            AbpSession = NullAbpSession.Instance;
            _context = context;
        }
    
        public async Task SendMessage(string message) {
            await _context.Clients.All.SendAsync("getMessage", string.Format("User {0}: {1}", AbpSession.UserId, message));
        }
    }
    
  3. Я изменил отображение URL '/ signalr' на MySignalRHub:

    public class Startup {
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) {
            [...]
            # if FEATURE_SIGNALR
                app.UseAppBuilder(ConfigureOwinServices);
            # elif FEATURE_SIGNALR_ASPNETCORE
                app.UseSignalR(routes => {
                    routes.MapHub<MySignalRHub>("/signalr");
                });
            # endif
            [...]
        }
    }
    
  4. Затем я использую концентратор для отправки сообщения в реализации сервиса:

    public class MyAppService: AsyncCrudAppService<MyEntity, MyDto, int, PagedAndSortedResultRequestDto, MyCreateDto, MyDto>, IMyAppService {
    
        private readonly IMySignalRHub _hub;
    
        public MyAppService(IRepository<MyEntity> repository, IMySignalRHub hub) : base(repository) {
            _hub = hub;
        }
    
        public override Task<MyDto> Create(MyCreateDto input) {
            _hub.SendMessage("test string").Wait();
            [...]
        }
    }
    

В клиенте

Все настройки и конфигурации уже включены в исходный шаблон. Когда я открываю приложение Angular, я вижу журналы этой консоли:

DEBUG: Connected to SignalR server!
DEBUG: Registered to the SignalR server!

Когда я пытаюсь вызвать серверную службу, которая отправляет сообщение клиенту, я получаю это предупреждение в консоли:

Warning: No client method with the name 'getMessage' found.

Я перепробовал много решений, найденных в официальной документации и в Интернете, но ни одно из них не сработало. Я не могу определить обработчик getMessage в клиентском коде.

Несколько нерабочих примеров, которые я пробовал:

Реализация 1:

// This point is reached
abp.event.on('getMessage', userNotification => {
    debugger; // Never reaches this point
});

Реализация 2:

// This point is reached
abp.event.on('abp.notifications.received', userNotification => {
    debugger; // Never reaches this point
});

Реализация 3:

// This is taken from the official documentation and triggers the error:
// ERROR TypeError: abp.signalr.startConnection is not a function
abp.signalr.startConnection('/signalr', function (connection) {
    connection.on('getMessage', function (message) {
        console.log('received message: ' + message);
    });
});

Вы когда-нибудь оказывались в такой ситуации? У вас есть простой рабочий пример определения обработчика в клиенте Angular?

UPDATE

Я попробовал это альтернативное решение, изменив реализацию класса SignalRAspNetCoreHelper (разделяемый класс, который поставляется с базовым шаблоном):

export class SignalRAspNetCoreHelper {
    static initSignalR(): void {

        var encryptedAuthToken = new UtilsService().getCookieValue(AppConsts.authorization.encrptedAuthTokenName);

        abp.signalr = {
            autoConnect: true,
            connect: undefined,
            hubs: undefined,
            qs: AppConsts.authorization.encrptedAuthTokenName + "=" + encodeURIComponent(encryptedAuthToken),
            remoteServiceBaseUrl: AppConsts.remoteServiceBaseUrl,
            startConnection: undefined,
            url: '/signalr'
        };

        jQuery.getScript(AppConsts.appBaseUrl + '/assets/abp/abp.signalr-client.js', () => {
            // ADDED THIS
            abp.signalr.startConnection(abp.signalr.url, function (connection) {
                connection.on('getMessage', function (message) { // Register for incoming messages
                    console.log('received message: ' + message);
                });
            });
        });
    }
}

Теперь в консоли я вижу оба сообщения:

Warning: No client method with the name 'getMessage' found.
SignalRAspNetCoreHelper.ts:22 received message: User 2: asd

Так что это работает, но не полностью. Где-то обработчик getMessage не виден. Как правильно реализовать обработчик сообщений в Angular с помощью ASP.NET Boilerplate?

Ответы [ 3 ]

0 голосов
/ 03 октября 2018

Вы должны использовать Clients.Others.SendAsync или Client.AllExcept.SendAsync вместо Clients.All.SendAsync.

Clients.All.SendAsync предназначен для сценариев, когда клиент хочет отправлять и получать сообщения (например, в чате). Следовательно, все подключенные клиенты должны реализовать connection.on('getMessage', для получения уведомлений. Если этого не произойдет, они выдадут предупреждение Не найдено ни одного клиентского метода с именем 'x' при получении обратно только что отправленного уведомления.

В вашем сценарии, как я понимаю, у вас есть один вид уведомлений, отправляемых клиентом, и другой тип, получающий их (например, устройство GPS, отправляющее позиции в приложение отслеживания). В этом случае использование Clients.Others.SendAsync или Client.AllExcept.SendAsync гарантирует, что отправка клиентов не будет транслироваться обратно на уведомление, которое они (или их вид) только что отправили.

0 голосов
/ 08 мая 2019

Я столкнулся с той же ошибкой в ​​моем приложении Angular, где я использую пакет "@aspnet/signalr": "1.1.4".

enter image description here

Причиной этой проблемы было то, что я не вызывал метод подписки после присоединения к каналу.

public async getWorkSheetById(worksheetId: string): Promise < Worksheet > {
    const worksheet: Worksheet = await this._worksheetService.getWorksheet(worksheetId);
    this.displayWorksheet(worksheet);
    await this._worksheetEventsService.joinWorksheetChannel(this._loadedWorksheet.id);
    return worksheet;
}

Итак, чтобы исправить это, я вызвал метод подписки после объединения await this.subscribeToSendMethod(this._loadedWorksheet))

public subscribeToSendMethod(loadedWorksheet: Worksheet): Worksheet {
    let newWorksheet: Worksheet;
    this._hubConnection.on('Send', (groupId: string, payloadType: string, payload: string, senderUserId: string)=> {
        newWorksheet=this._worksheetHandler.handlePayload(payloadType, payload, loadedWorksheet);
        this.displayWorksheet(newWorksheet);
    }
    );
    return newWorksheet;
}
0 голосов
/ 05 июля 2018

Установите autoConnect: false, чтобы установить собственное соединение:

abp.signalr = {
    autoConnect: false,
    // ...
};

Еще лучше ...

Не расширять AbpCommonHub. Вы обнаружите, что уведомление в режиме реального времени перестает работать, и вам нужно заменить IRealTimeNotifier, потому что SignalRRealTimeNotifier использует AbpCommonHub.

У вас есть простой рабочий пример определения обработчика в клиенте Angular?

Как правильно реализовать обработчик сообщений в Angular с ASPNet Boilerplate?

Следуйте документации и создайте отдельный концентратор.

...