MVC, Angular 8 and signalR random behavior, not connect to hub sometimes, how to fix it?

Sometimes Angular component doesn't connect to ASP.Net-MVC Server and sometimes it does, usually when i clean cache it is more likely that it will work, but it isn't always the case.

This is a similar case to my situation: SignalR ConnectionData empty, and won't connect

SERVICE

import { Injectable } from '@angular/core';
import { Defs } from '../tools/defs';

declare var $: any;

@Injectable({
  providedIn: 'root'
})
export class SignalRService {
  private proxy: any; 
  private connection: any; 
  private waitedAnswer:string;
  constructor() { }
/*
  public setSignalRConnection(group: string){
    this.initializeSignalRConnection();
    this.addListener(group);
  }
  */
  public initializeSignalRConnection(): void {
    let signalRServerEndPoint = Defs.URL + 'signalr';
    this.connection = $.hubConnection(signalRServerEndPoint, { useDefaultPath: false });
    this.connection.logging = true;
    this.proxy = this.connection.createHubProxy('MyHub');
    this.startConnection();
  }

  private startConnection(){
    this.connection.start({ jsonp: true, cache: false }).done((msg: any) => {
      console.log(msg);
      console.log(msg.data);
      this.waitedAnswer = msg.data;
      /*if (msg.data != '[]') {
        console.log('Connected to Notification Hub');
      } else {
        this.startConnection();
        console.log('Retrying');
      }*/
    }).catch((error: any) => {
      console.log(error);
    });
  }

  public addListener(group: string) : void {
    console.log("addListener");
    this.proxy.on(group, (data: any) => {
      //location.reload();
      console.log(data);
      console.log("PERFECTÍSIMO");
    });

  }


  public broadcastMessage(message: string): void {
    this.proxy.invoke('Notify', message)
      .catch((error: any) => {
        console.log('broadcastMessage error -> ' + error);
      });
  }

}

COMPONENT

import { Component, OnInit, ElementRef, ViewChild, Renderer } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Document } from '../../entities/Document';
import { Host } from '../../entities/host';
import { Defs } from '../../tools/defs';
import { Router } from '@angular/router';
import { LoadingService } from '../../services/loading.service';
import { SignalRService } from '../../services/signal-r.service';
import { MySnackBarService } from '../../services/my-snack-bar.service';
import { MatDialog } from '@angular/material/dialog';
import { HostNotExistDialogComponent } from '../../components/home/host-not-exist-dialog/host-not-exist-dialog.component';
import { Product } from '../../entities/product';
import { MatSidenav } from '@angular/material';
import { ConfiguratorUserService } from '../../services/configurator-user.service';

@Component({
  selector: 'app-root',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.sass']
})
export class HomeComponent implements OnInit {

...

  constructor(private httpClient: HttpClient, private router: Router, public loading: LoadingService, public mySnackBarService: MySnackBarService, 
public dialog: MatDialog, 
public signalRService: SignalRService, private renderer: Renderer, 

public configuratorUserService: ConfiguratorUserService) {
    this.inicialize();
    this.signalRService.initializeSignalRConnection();
  }

....

  private requestDocuments() {
    this.loading.show();
    this.httpClient.get(Defs.BASE_APPI_URL + 'Documents/')
      .subscribe((res: Host) => {
           this.signalRService.addListener(this.host.DatabaseSettingId);
        }
      }, error => {
          ....
          }          
      });
  }


}

I receive this when the connection is successfully:

init {url: "../signalr", qs: null, lastError: null, _: {…}, logging: true, …}
ajaxDataType: "jsonp"
appRelativeUrl: "/signalr"
baseUrl: "http://localhost:51136"
data: "[{"name":"myhub"}]"
disconnectTimeout: 30000
host: "localhost:51136"
id: "049ef74a-2e85-4be9-b22e-348dd463dd48"
lastError: null
logging: true
messageId: "d-7926811B-D,0|G,0|H,1"
pollXhr: {readyState: 1, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …}
protocol: "http:"
proxies: {myhub: init}
qs: null
reconnectWindow: 50000
state: 1
token: "kjGd+9BFtb6n2+hu1U+YmsAQtp224SkWD82ffXWg1Ip7bjzpf6E1YMgrA1h7MnRpiNJnnAD8HrKY9/pMDSFGGnrH5EZEwPtUu8NYenIG+saq1OjQWFXwunYNbTDJ7I5B"
transport: {name: "longPolling", supportsKeepAlive: ƒ, reconnectDelay: 3000, start: ƒ, lostConnection: ƒ, …}
url: "../signalr"
webSocketServerUrl: undefined
withCredentials: undefined
wsProtocol: "ws://"
_: {keepAliveData: {…}, connectingMessageBuffer: h, lastMessageAt: 1567113642710, lastActiveAt: 1567113660266, beatInterval: 2222.2222222222226, …}
_deferral: {notify: ƒ, notifyWith: ƒ, resolve: ƒ, resolveWith: ƒ, reject: ƒ, …}
_originalUrl: "../signalr"
_subscribedToHubs: true
jQuery3410464314750711154471: {events: {…}, handle: ƒ}
__proto__: Object

and when it is not:

init {url: "../signalr", qs: null, lastError: null, _: {…}, logging: true, …}
ajaxDataType: "jsonp"
appRelativeUrl: "/signalr"
baseUrl: "http://localhost:51136"
data: "[]"
disconnectTimeout: 30000
host: "localhost:51136"
id: "049ef74a-2e85-4be9-b22e-348dd463dd48"
lastError: null
logging: true
messageId: "d-7926811B-D,0|G,0|H,1"
pollXhr: {readyState: 1, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …}
protocol: "http:"
proxies: {myhub: init}
qs: null
reconnectWindow: 50000
state: 1
token: ... 3000, start: ƒ, lostConnection: ƒ, …}
url: "../signalr"
webSocketServerUrl: undefined
withCredentials: undefined
wsProtocol: "ws://"
_: {keepAliveData: {…}, connectingMessageBuffer: h, lastMessageAt: 1567113642710, lastActiveAt: 1567113660266, beatInterval: 2222.2222222222226, …}
_deferral: {notify: ƒ, notifyWith: ƒ, resolve: ƒ, resolveWith: ƒ, reject: ƒ, …}

THE ONLY DIFFERENCE IS data: "[]" AND data: "[{"name":"myhub"}]"

Backend

using System;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNet.SignalR;
using System.Web.Http.Cors;
using Microsoft.AspNet.SignalR.Hubs;

namespace QualityNotebook.Controllers.SignalR
{
    [HubName("MyHub")]
    public class AlertHub : Hub
    {
        public void Notify(string message)
        {

        }
        public override Task OnConnected()
        {//When I debug sometimes it fires, sometimes it doesn't
            return base.OnConnected();
        }
    }
}

Upvotes: 3

Views: 1175

Answers (1)

I decided to close the connection when it is empty '[]' and try to connect my hub again and it worked very well, I know it is not a perfect solution but it saved me from the hurry.

import { Injectable } from '@angular/core';
import { Defs } from '../tools/defs';

declare var $: any;

@Injectable({
  providedIn: 'root'
})
export class SignalRService {
  private proxy: any; 
  private connection: any; 
  private waitedAnswer: string = '[]';
  public groupKey: string = 'key';
  constructor() { }

  public setSignalRConnection(group: string){
      this.initializeSignalRConnection();
      this.addListener(group);
  }

  public initializeSignalRConnection(): void {
    let signalRServerEndPoint = Defs.URL + 'signalr'; //+ '?test=' + new Date();
    this.connection = $.hubConnection(signalRServerEndPoint, { useDefaultPath: false });
    this.connection.logging = true;
    this.proxy = this.connection.createHubProxy('MyHub');
    this.startConnection();
    this.ifConnectionIsLose();
  }

  private ifConnectionIsLose(){
    this.connection.disconnected(function () {
      setTimeout(() => {   
        this.startConnection();
        this.addListener(this.groupKey);
      }, 5000);
    });
  }

  public startConnection(){
    console.log(this.connection);
    this.connection.start({ jsonp: true, cache: false }).done((msg: any) => {
      console.log("Data Receive from signalR message: " + msg.data);
      this.waitedAnswer = msg.data;
      if (msg.data=='[]'){
        this.connection.stop();
        setTimeout(() => {
          this.startConnection();
          this.addListener(this.groupKey);
          console.log("groupKey: " + this.groupKey);
        }, 1000);
      }
    }).catch((error: any) => {
      console.log(error);
    });
  }

  public addListener(group: string) : void {
    console.log("addListener");
    this.groupKey = group;
    this.proxy.on(group, (data: any) => {
      //location.reload();
      console.log(typeof data);
      console.log("PERFECTÍSIMO");
    });
  }

  public broadcastMessage(message: string): void {
    this.proxy.invoke('Notify', message)
      .catch((error: any) => {
        console.log('broadcastMessage error -> ' + error);
      });
  }
}

Upvotes: 1

Related Questions