gvd*_*vdm 4 c# typescript asp.net-core aspnetboilerplate asp.net-core-signalr
我有一个 ASP.NET Boilerplate v3.6.2 项目(.NET Core / Angular),其中我需要从后端方法调用客户端函数,因此我使用 ASP.NET Core SignalR 实现。
我按照官方文档,所以:
在后台
在我的模块中,我将依赖项添加到AbpAspNetCoreSignalRModule:
[DependsOn(typeof(AbpAspNetCoreSignalRModule))]
public class MyModule : AbpModule
Run Code Online (Sandbox Code Playgroud)
并将此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));
}
}
Run Code Online (Sandbox Code Playgroud)我将 '/signalr' url 的映射更改为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
[...]
}
}
Run Code Online (Sandbox Code Playgroud)然后我使用集线器在服务实现中发送消息:
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();
[...]
}
}
Run Code Online (Sandbox Code Playgroud)在客户端
所有配置和包含内容均已在原始模板中就位。当我打开 Angular 应用程序时,我可以看到以下控制台日志:
DEBUG: Connected to SignalR server!
DEBUG: Registered to the SignalR server!
Run Code Online (Sandbox Code Playgroud)
当我尝试调用向客户端发送消息的后端服务时,我在控制台中收到此警告:
Warning: No client method with the name 'getMessage' found.
Run Code Online (Sandbox Code Playgroud)
我尝试了官方文档和互联网上找到的许多解决方案,但没有一个起作用。我无法在客户端代码中定义“getMessage”处理程序。
我尝试过的一些无效示例:
实施1:
// This point is reached
abp.event.on('getMessage', userNotification => {
debugger; // Never reaches this point
});
Run Code Online (Sandbox Code Playgroud)
实施2:
// This point is reached
abp.event.on('abp.notifications.received', userNotification => {
debugger; // Never reaches this point
});
Run Code Online (Sandbox Code Playgroud)
实施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);
});
});
Run Code Online (Sandbox Code Playgroud)
您是否曾经遇到过这样的情况?您有 Angular 客户端中处理程序定义的简单工作示例吗?
我尝试了这种替代解决方案,更改了类的实现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);
});
});
});
}
}
Run Code Online (Sandbox Code Playgroud)
现在在控制台中我可以看到两条消息:
Warning: No client method with the name 'getMessage' found.
SignalRAspNetCoreHelper.ts:22 received message: User 2: asd
Run Code Online (Sandbox Code Playgroud)
所以它正在发挥作用,但并不完全。“getMessage”处理程序在某处不可见。使用 ASP.NET Boilerplate 在 Angular 中实现消息处理程序的正确方法是什么?
小智 5
您应该使用Clients.Others.SendAsyncorClient.AllExcept.SendAsync代替Clients.All.SendAsync.
Clients.All.SendAsync专为客户端想要发送和接收消息的场景(如聊天室)而设计。因此,所有连接的客户端都应该实现connection.on('getMessage',才能接收通知。如果不这样做,他们会在收到刚刚推送的通知时发出警告“找不到名为“x”的客户端方法” 。
在您的场景中,我知道您有一种客户端推送通知,另一种客户端接收通知(例如 GPS 设备将位置发送到跟踪应用程序)。在这种情况下,使用Clients.Others.SendAsync或Client.AllExcept.SendAsync将确保推送客户端不会被广播回他们(或他们的同类)刚刚推送的通知。
| 归档时间: |
|
| 查看次数: |
10961 次 |
| 最近记录: |