Reconnect to group with SignalR

I have a chat application with SignalR in Net5 and @microsoft/signalr in Angular12. The problem I have is when the connection is lost, i need to reconnect and rejoin a group, the reconnection does work but the reconnection to a group does not.

The function I use to join a group in signalr.service.ts is:

 addTogroup(room: any,user:any)

The method I use to recover the connection in signalr.service.ts is:

.withAutomaticReconnect({
    nextRetryDelayInMilliseconds: retryContext => {
      if (retryContext.elapsedMilliseconds < 60000) {
        // If we've been reconnecting for less than 60 seconds so far,
        // wait between 0 and 10 seconds before the next reconnect attempt.

        return Math.random() * 10000;
      } else {
        // If we've been reconnecting for more than 60 seconds so far, stop reconnecting.
        return null;
      }
    }
  })

Is it possible to access in any way the function that joins you to a group, when the withAutomaticReconnect is being executed? To join the group you need the user and the room that are in app.component.ts

Thank you very much for the help, I have already read the documentation many times but I cannot find the solution.

My code is:

app.component.ts

import { Component, OnInit, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { SignalrService } from '../services/signalr.service';
import { HttpClient } from '@angular/common/http';
import { i18nMetaToJSDoc } from '@angular/compiler/src/render3/view/i18n/meta';


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  @ViewChild('myinputfile') myinputfile: any;

  title = 'chat-ui';
  listMessages: any[] = [];
  messages: string[] = [];
  message: string = "";
  user: string = "";
  ticket: string = "";
  currentFiles: any = [];
  myimg: any = "";

  constructor(public signalrService: SignalrService, private http: HttpClient) {

  }

  ngOnInit(): void {
    this.signalrService.startConnection((message: any) => {
      this.listMessages.push({ mensaje: message.mensaje, user: message.user, tipo: "texto" });
    }, (imageMessage: any) => {
      this.listMessages.push(imageMessage);
    }, (incomingConnection: any) => {
      console.log(incomingConnection);
    }, (error:any) => {
      console.log(error);
    });
  }

  addRoom() {
    this.signalrService.addTogroup(this.ticket, this.user);
  }

  async sendMessage() {
    if (this.myinputfile.nativeElement.files.length > 0) {
      let formData = new FormData();

      formData.append("RoomId", this.ticket);
      formData.append("IdUsuario", this.user);
      formData.append("IdCliente", "1");
      formData.append("Interno", "1");
      formData.append("File", this.myinputfile.nativeElement.files[0]);

      await this.signalrService.sendImagesMessage(formData, (response: any) => {
        this.myimg = response;
      }, (error: any) => {
        console.log(error);
      });

      this.myinputfile.nativeElement.value = "";
    } else {
      this.signalrService.sendMessageGroup(this.ticket, this.user, this.message);
    }
  }

  onaddremoveFiles() {
    if (this.myinputfile.nativeElement.files.length == 0) {
      this.myinputfile.nativeElement.click();
    } else {
      this.myinputfile.nativeElement.value = "";
    }
  }

  onfilesSelected(files: any) { return files.length > 0; }

  openImages(src: any) {
    let data = src;
    let w = window.open('about:blank');
    let image = new Image();
    image.src = data;

    if (w !== null) {
      w.document.write(image.outerHTML);
    }
  }
}

signalr.service.ts

import { Injectable } from '@angular/core';
import * as signalR from "@microsoft/signalr";
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class SignalrService {
  public hubConnection!: signalR.HubConnection;

  constructor(private http:HttpClient) {
    this.buildConnection();
    //this.startConnection();
   }

  public buildConnection = () => {
    this.hubConnection = new signalR.HubConnectionBuilder()
      .configureLogging(signalR.LogLevel.Information)
      .withUrl("https://localhost:44352/chatHub",{
        skipNegotiation: true,
        transport: signalR.HttpTransportType.WebSockets
      })
      //.withAutomaticReconnect([0,1000,5000,6000,7000,8000,10000,15000])
      .withAutomaticReconnect({
        nextRetryDelayInMilliseconds: retryContext => {
            if (retryContext.elapsedMilliseconds < 60000) {
                // If we've been reconnecting for less than 60 seconds so far,
                // wait between 0 and 10 seconds before the next reconnect attempt.

                return Math.random() * 10000;
            } else {
                // If we've been reconnecting for more than 60 seconds so far, stop reconnecting.
                return null;
            }
        }
    })
      .build();
  };

  public startConnection = (
    onMessageCallback:Function,
    onMessageImageCallback:Function, 
    onIncomingConnectionCallback:Function,
    onErrorCallback:Function) => {
    this.hubConnection
      .start()
      .then(() => {
        console.log("Connection Started...");
        this.ListeningConnections();
        this.ListeningIncomeMessages(onMessageCallback);
        this.ListeningIncomeImagesMessages(onMessageImageCallback);
        this.ListeningIncomingConnection(onIncomingConnectionCallback);
        this.ListeningError(onErrorCallback);
      })
      .catch(err => {
        /*console.log("Error while starting connection: " + err);
        setTimeout(() => {
          this.startConnection();
        }, 3000);*/
      });
  };

  private ListeningConnections(){
    this.hubConnection.on("ReceiveConnID", function (connid) {
      console.log("ConnID: " + connid);
    });
  }
  
  public addTogroup(room: any,user:any){
    this.hubConnection.invoke("AddToGroup", room, user);
  }

  public sendMessageGroup(room: any,user:any,message:any){
    this.hubConnection.invoke("SendMessageGroup",room, user,message,0)
    .catch(function (err) {
      return console.error(err.toString());
    });     
  }

  public ListeningIncomeMessages(onMessageCallback:Function){
    this.hubConnection.on("ReceiveMessageGroup",  (user, message) => {    
      onMessageCallback({mensaje: message, user: user});
    });  
  }

  public ListeningIncomingConnection(onIncomingConnectionCallback:Function){
    this.hubConnection.on("IncomingConnection",(message) => {    
      onIncomingConnectionCallback({mensaje: message});
    });  
  }

  public ListeningUserConnected(onMessageCallback:Function){
    this.hubConnection.on("ReceiveMessageUserConnected",  (user, message) => {    
      onMessageCallback({mensaje: message, user: user});
    });  
  }

  public ListeningError(onErrorCallback:Function){
    this.hubConnection.on("onError", (message) => {    
      onErrorCallback({mensaje: message});
    });  
  }

  public ListeningIncomeImagesMessages(onImageMessageCallback:Function){
    this.hubConnection.on("ReceiveImageMessageGroup", (user, image) => {
      //console.log(image);
     // console.log(image.idUsuario);
     // console.log(image.idCliente);

      onImageMessageCallback({ mensaje: image, user: user, tipo: "imagen" });
    });
  }

  public async sendImagesMessage(formData:FormData,onOkCallback:Function,onErroCallback:Function){
    await this.http.post("https://localhost:44352/UploadImages",formData).toPromise().then((response)=>{
      onOkCallback(response);
    }).catch((error)=>{
      onErroCallback(error);
      console.log(error);
    });
  }  
}

ChatHub.cs

    public class ChatHub : Hub
    {
        public readonly static List<UserViewModel> _Connections = new List<UserViewModel>();
        public readonly static List<RoomViewModel> _Rooms = new List<RoomViewModel>();
        private readonly static Dictionary<string, string> _ConnectionsMap = new Dictionary<string, string>();

        private readonly TicketingContext _context;
        private readonly IMapper _mapper;

        private readonly IMensajeService _mensajeService;
        private readonly IUnitOfWork _unitOfWork;
        public ChatHub(TicketingContext context, IUnitOfWork unitOfWork, IMensajeService mensajeService, IMapper mapper)
        {
            _context = context;
            _mensajeService = mensajeService;
            _unitOfWork = unitOfWork;
            _mapper = mapper;
        }

        public IEnumerable<RoomViewModel> GetRooms()
        {
            if (_Rooms.Count == 0)
            {
                foreach (var room in _context.Tickets)
                {
                    var roomViewModel = _mapper.Map<Tickets, RoomViewModel>(room);
                    _Rooms.Add(roomViewModel);
                }
            }
            return _Rooms.ToList();
        }

        public IEnumerable<UserViewModel> GetUsers(string roomName)
        {
            return _Connections.Where(u => u.CurrentRoom == roomName).ToList();
        }

        //envia mensajes a un grupo determinado
        public async Task SendMessageGroup(string room, string user, string message, int interno)
        {
            try
            {
                var msg = new MensajeGrabarDto()
                {
                    IdTicket = Int32.Parse(room),
                    IdUsuario = Int32.Parse(user),
                    Texto = Regex.Replace(message, @"(?i)<(?!img|a|/a|/img).*?>", string.Empty),
                    Interno = interno,
                    Adjunto = new byte[] { },
                    AdjuntoNombre = "",
                    AdjuntoTipo = ""
                    //llenar los campos
                };

                DbResponse respon = await _unitOfWork.MensajeRepository.InsertarMensajeRepository(msg);           

                if (respon.retcode == 0)
                {
                    await _unitOfWork.SaveChangesAsync();

                    var mensaje = await _mensajeService.ObtenerMensajesPorTicketService(Int32.Parse(room));

                    var mensaje2 = mensaje.Where(x => x.IdTicket == Int32.Parse(room)).OrderByDescending(x => x.IdMensaje).FirstOrDefault();

                    await Clients.Group(room).SendAsync("ReceiveMessageGroup", user, mensaje2);
                }
                else {
                    await Clients.Caller.SendAsync("onError", respon.mensaje);
                }
            }
            catch (Exception)
            {
                await Clients.Caller.SendAsync("onError", "Message not send! Message should be 1-1500 characters.");
            }

        }

        //une a un usuario a determinado grupo
        public async Task AddToGroup(string room, string usuario) 
        {
            try
            {
                await Groups.AddToGroupAsync(Context.ConnectionId, room);

                //mensaje para decir que alguien se conecto
                await Clients.Group(room).SendAsync("IncomingConnection", $"Alguien se conecto { usuario}");
            }
            catch (Exception ex)
            {
                await Clients.Caller.SendAsync("onError", "You failed to join the chat room!" + ex.Message);
            }            
        }

        //desloguea a un usuario de un grupo
        public async Task Leave(string roomName)
        {
            await Groups.RemoveFromGroupAsync(Context.ConnectionId, roomName);
        }

        public override Task OnConnectedAsync()
        {
            try
            {
                Clients.Client(Context.ConnectionId).SendAsync("ReceiveConnID", Context.User.Identity.Name);
            }
            catch (Exception ex)
            {
                Clients.Caller.SendAsync("onError", "OnConnected:" + ex.Message);
            }
            return base.OnConnectedAsync();
        }

        public override Task OnDisconnectedAsync(Exception exception)
        {
            try
            {

            }
            catch (Exception ex)
            {
                Clients.Caller.SendAsync("onError", "OnDisconnected: " + ex.Message);
            }

            return base.OnDisconnectedAsync(exception);
        }
    }