2
votes

I have multiple signalR hub in .net core 3.1 web api. I want to access 2 hub at the same page but i don't need one of them at other pages. I search about signalR and i figure out all hubs use same connection so i couldn't stop connection. And on my project i don't know how to seperate hubs in angular. Can anyone help me about how to use multiple hubs in angular and is there any way to close hub connection instead signalr connection.

Here is my code;

ChartHub.cs

  public class ChartHub : Hub
    {
        public async Task BroadcastChartData(List<ChartModel> data) =>
        await Clients.All.SendAsync("broadcastchartdata", data);
    }

UserHub.cs

    public class UserHub : Hub
    {
        static List<string> userlist = new List<string>() {.....};

        public async Task addUser() {
          await Task.Run(() => {
             userlist.add(Context.ConnectionId);
          });
        } 

        public async Task GetUserList() =>
        await Clients.All.SendAsync("getuserlist", data);
    }

Startup.cs

app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapHub<ChartHub>("/charthub");
            endpoints.MapHub<UserHub>("/userhub");
        });

SignalRService.ts

 private hubConnection: signalR.HubConnection
  private thenable: Promise<void>
  public data: any;

  public startConnection = (hubname) => {
    this.hubConnection = new signalR.HubConnectionBuilder()
      .withUrl('https://localhost:44398' + hubname)
      .withAutomaticReconnect()
      .configureLogging(signalR.LogLevel.Information)
      .build();
    this.start();
  }

  private start() {
    this.thenable = this.hubConnection.start();
    this.thenable
      .then(() => console.log('Connection started!'))
      .catch(err => console.log('Error while establishing connection :('));
  }

  public broadcastChartData = () => {
  const data = this.data.map(m => {
    const temp = {
      data: m.data,
      label: m.label
    }
    return temp;
  });
  this.thenable.then(() => {
    this.hubConnection.invoke('broadcastchartdata', data)
      .catch(err => console.error(err));
  });
}
public addBroadcastChartDataListener = () => {
  this.thenable.then(() => {
    this.hubConnection.on('broadcastchartdata', (data) => {
      console.log('broadcasted Data : ',data);
    });
  });
 }

 public userData = () => {
  const data = this.data.map(m => {
    const temp = {
      data: m.data,
      label: m.label
    }
    return temp;
  });
  this.thenable.then(() => {
    this.hubConnection.invoke('adduser')
      .catch(err => console.error(err));
  });
}
public addGetUserListListener = () => {
  this.thenable.then(() => {
    this.hubConnection.on('getuserlist', (data) => {
      console.log('userlist Data : ',data);
    });
  });
}

app.component.ts

constructor(public signalRService: SignalRService) {}
//I want to use hubs like this.
  ngOnInit(): void {
    this.signalRService.startConnection("/userhub");
    this.signalRService.startConnection("/charthub");
    
    this.signalRService.addGetUserListListener();
    this.signalRService.addBroadcastChartDataListener();

    //A hub throws method not found exception.
    this.signalRService.userData();
    this.signalRService.broadcastChartData(); 
    }

Question; I don't know how to use 2 seperated hub at the same time in angular and don't know how to dispose any hub connection when i don't need it anymore.

1

1 Answers

4
votes

You can start two separate connections and then stop the connection n#2, here is an example:

/**
 * Configure signalR
 */
private configureSignalR(signalRUrl: string, token: string) {
  this.hubMessageConnection = new signalR.HubConnectionBuilder()
    .configureLogging(signalR.LogLevel.Error).withUrl(signalRUrl + "/userhub",
      {
        accessTokenFactory: () => token
      })
    .withAutomaticReconnect()
    .build();

    this.hubMessageConnection2 = new signalR.HubConnectionBuilder()
    .configureLogging(signalR.LogLevel.Error).withUrl(signalRUrl + "/chartHub",
      {
        accessTokenFactory: () => token
      })
    .withAutomaticReconnect()
    .build();
}

/**
* Connect signalR
*/
private async connectSignalR() {
  await this.hubMessageConnection.start()
    .then(() => {
      // Register application
      this.registerApplication();
    }).catch(() => {
      this.onError.emit(WidgetStateEnum.connectError);
    });

    await this.hubMessageConnection2.start()
    .then(() => {
      // Register application
      this.registerApplication();
    }).catch(() => {
      this.onError.emit(WidgetStateEnum.connectError);
    });
}

/**
 * Disconnect signalR connection n#2
 */
private async disconnectSignalR() {
  this.hubMessageConnection2.stop();
}