У меня есть проект ASP.NET Boilerplate v3.6.2 (.NET Core / Angular), в котором мне нужно вызвать клиентскую функцию из внутреннего метода, поэтому я использую реализацию ASP.NET Core SignalR .
Я следовал официальной документации, поэтому:
В бэкэнде
В моем модуле я добавил зависимость к AbpAspNetCoreSignalRModule
:
[DependsOn(typeof(AbpAspNetCoreSignalRModule))]
public class MyModule : AbpModule
И добавил этот пакет NuGet в проект модуля.
Затем я расширил класс 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));
}
}
Я изменил отображение 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
[...]
}
}
Затем я использую концентратор для отправки сообщения в реализации сервиса:
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?