public async Task Join(string groupId) { var existingGroup = chatGroups.FirstOrDefault(x => x.PublicId == groupId); if (existingGroup == null) { await Clients.Caller.SendAsync(receiveMethodName, MessageConstructor.SystemMessage(ErrorMessages.GroupDoesNotExist(groupId))); return; } var groupName = existingGroup.Name; if (existingGroup.CurrentClientsAmount == existingGroup.MaximumClientsAmount) { await Clients.Caller.SendAsync(receiveMethodName, MessageConstructor.SystemMessage(InformationMessages.ClientsInGroupLimitReached(groupName, _appConfig.MaximumGroupSize))); return; } if (existingGroup.ClientsConnected.FirstOrDefault(x => x == Context.ConnectionId) != null) { await Clients.Caller.SendAsync(receiveMethodName, MessageConstructor.SystemMessage(ErrorMessages.AlreadyAGroupMember(groupName))); return; } var groupHistoryToClientDto = await _processor.OnGroupJoin(existingGroup.PublicId, Context.ConnectionId); var groupMessage = new GroupMessage { GroupName = groupName, GroupId = existingGroup.PublicId }; existingGroup.ClientsConnected.Add(Context.ConnectionId); var exclutionList = new List <string> { Context.ConnectionId }; Task.WaitAll( Groups.AddToGroupAsync(Context.ConnectionId, groupName), Clients.Caller.SendAsync(receiveMethodName, MessageConstructor.SystemMessage(InformationMessages.SuccessfullyJoinedGroup(groupName))), Clients.Caller.SendAsync(GroupMethodNames.OnGroupJoined, groupMessage), Clients.Caller.SendAsync(GroupMethodNames.ReceiveGroupHistory, MessageConstructor.GroupMessageHistory(groupHistoryToClientDto)), Clients.GroupExcept(groupName, exclutionList) .SendAsync(receiveMethodName, MessageConstructor.SystemMessage(InformationMessages.ClientHasJoinedGroup(groupHistoryToClientDto.Client.PublicName)))); }