我正在使用Angular前端创建一个运行在4.7上的ASP.NET核心应用程序。因为我需要通知用户有关状态更改的信息,我试图添加SignalR。我使用以下版本:
下面你可以看到我的代码。如果我运行这个应用程序,我可以在日志中看到两个集线器连接都已开始。如果我打开具有相同URL的第二个浏览器选项卡,则只有一个连接成功。对于第二个集线器,我总是会收到此错误:
Error: Not Found
at XMLHttpRequest.xhr.onload [as __zone_symbol__ON_PROPERTYload] (http://localhost:51616/dist/estructuring_main.js?v=fBx34vrzWnqBIPjAm71NaWQz0TEeQZWcx2ixKnjADWI:36168:28)
at XMLHttpRequest.wrapFn (http://localhost:51616/dist/vendor.js?v=rp1X6LsN5SJnsTJrd-749xunuUaKAA_WINwoqzbaeqE:120085:39)
at ZoneDelegate.invokeTask (http://localhost:51616/dist/vendor.js?v=rp1X6LsN5SJnsTJrd-749xunuUaKAA_WINwoqzbaeqE:119340:31)
at Object.onInvokeTask (http://localhost:51616/dist/vendor.js?v=rp1X6LsN5SJnsTJrd-749xunuUaKAA_WINwoqzbaeqE:5013:33)
at ZoneDelegate.invokeTask (http://localhost:51616/dist/vendor.js?v=rp1X6LsN5SJnsTJrd-749xunuUaKAA_WINwoqzbaeqE:119339:36)
at Zone.runTask (http://localhost:51616/dist/vendor.js?v=rp1X6LsN5SJnsTJrd-749xunuUaKAA_WINwoqzbaeqE:119107:47)
at ZoneTask.invokeTask [as invoke] (http://localhost:51616/dist/vendor.js?v=rp1X6LsN5SJnsTJrd-749xunuUaKAA_WINwoqzbaeqE:119415:34)
at invokeTask (http://localhost:51616/dist/vendor.js?v=rp1X6LsN5SJnsTJrd-749xunuUaKAA_WINwoqzbaeqE:120436:14)
at XMLHttpRequest.globalZoneAwareCallback (http://localhost:51616/dist/vendor.js?v=rp1X6LsN5SJnsTJrd-749xunuUaKAA_WINwoqzbaeqE:120462:17)
错误说404找不到,即使我可以在我的请求 - 中间件中看到请求。
我需要更改集线器连接是否也适用于多个标签?
Startup.cs
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddSignalR();
services.AddSingleton(typeof(IUserTracker<>), typeof(InMemoryUserTracker<>));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime appLifetime)
{
app.UseSignalR(routes =>
{
routes.MapHub<StatusHub>("status", (options) =>
{
options.Transports = TransportType.LongPolling;
});
routes.MapHub<AutopricerHub>("autopricer", (options) =>
{
options.Transports = TransportType.LongPolling;
});
});
}
InMemoryUserTracker.cs
public class InMemoryUserTracker<THub> : IUserTracker<THub>
{
private readonly ConcurrentDictionary<HubConnectionContext, UserDetails> usersOnline
= new ConcurrentDictionary<HubConnectionContext, UserDetails>();
public IEnumerable<UserDetails> UsersOnline()
=> usersOnline.Values.AsEnumerable();
public Task AddUser(HubConnectionContext connection, UserDetails userDetails)
{
usersOnline.TryAdd(connection, userDetails);
return Task.CompletedTask;
}
public Task RemoveUser(HubConnectionContext connection)
{
usersOnline.TryRemove(connection, out var userDetails);
return Task.CompletedTask;
}
}
BaseHubWithPresence.cs
public abstract class BaseHubWithPresence : Hub
{
protected readonly IUserTracker<BaseHubWithPresence> userTracker;
protected BaseHubWithPresence(IUserTracker<BaseHubWithPresence> userTracker)
{
this.userTracker = userTracker;
}
public virtual async Task Join(long userId)
{
await userTracker.AddUser(Context.Connection, new UserDetails(Context.ConnectionId, userId));
await Task.CompletedTask;
}
public virtual async Task Leave()
{
await userTracker.RemoveUser(Context.Connection);
await Task.CompletedTask;
}
}
AutopricerHub.cs
public class AutopricerHub : BaseHubWithPresence
{
public AutopricerHub(IUserTracker<AutopricerHub> userTracker)
: base(userTracker) {}
public async Task SendToAll()
{
await Clients.All.InvokeAsync("All", "data");
}
public async Task SendUpdateAsync(long userId)
{
foreach (var user in userTracker.UsersOnline().Where(o => o.UserId == userId))
{
await Clients.Client(user.ConnectionId).InvokeAsync("Update", "data");
}
}
}
StatusHub.cs
public class StatusHub : BaseHubWithPresence
{
public StatusHub(IUserTracker<BaseHubWithPresence> userTracker)
: base(userTracker)
{
}
public async Task SendSingleAsync(long listener)
{
foreach (var user in userTracker.UsersOnline().Where(o => o.UserId == listener))
{
await Clients.Client(user.ConnectionId).InvokeAsync("Update", "data");
}
}
public async Task SendMultipleAsync(IReadOnlyCollection<long> listeners)
{
foreach (var listener in listeners)
{
foreach (var user in userTracker.UsersOnline().Where(o => o.UserId == listener))
{
await Clients.Client(user.ConnectionId).InvokeAsync("Update", "data");
}
}
}
}
price-notification.service.ts
@Injectable()
export class PriceNotificationService {
private hubConnection: HubConnection;
private destroy$ = new Subject<boolean>();
constructor(
private appContextService: AppContextService,
private messageService: MessageService) {
this.init();
}
private init(): void {
this.hubConnection = new HubConnection('/autopricer', { transport: TransportType.LongPolling });
this.hubConnection.start()
.then(() => {
this.appContextService.getAppContext().takeUntil(this.destroy$).subscribe(appContext => {
this.hubConnection.invoke('join', appContext.FirmuserId);
});
DEBUG.init && debug('Price Notification Hub connection started');
})
.catch(err => {
DEBUG.init && debug('Error while establishing Price Notification Hub connection');
});
this.hubConnection.onclose = e => {
DEBUG.functionCalls && debug('On close Price Notification Hub connection');
this.hubConnection.invoke('leave');
};
this.hubConnection.off('leave', null);
}
private showUpdateNotification(data: string) {
}
private showAllNotification(data: string) {
}
}
status-notification.service.ts
@Injectable()
export class StatusNotificationService {
private hubConnection: HubConnection;
private destroy$ = new Subject<boolean>();
constructor(
private appContextService: AppContextService,
private messageService: MessageService) {
this.init();
}
private init(): void {
this.hubConnection = new HubConnection('/status', { transport: TransportType.LongPolling });
this.hubConnection.start()
.then(() => {
this.appContextService.getAppContext().takeUntil(this.destroy$).subscribe(appContext => {
this.hubConnection.invoke('join', appContext.FirmuserId);
});
DEBUG.init && debug('Status Notification Hub connection started');
})
.catch(err => {
DEBUG.init && debug('Error while establishing Status Notification Hub connection');
});
this.hubConnection.onclose = e => {
DEBUG.functionCalls && debug('On close Status Notification Hub connection');
this.hubConnection.invoke('leave');
};
this.hubConnection.off('leave', null);
}
private showUpdateNotification(data: string) {
}
}
每个Angular服务的服务提供者都在一个单独的组件中。