i have "HubConnection.connectionClosed(null) called while in state HubConnectionState.connected" problem in flutter app for connecting signalR hub

Viewed 1197

this my code into flutter app for connecting to signalR project made in Blazor server side app and Net Core 3.1 my web hub project works correctly but i have problem in android side for connection and working ;

import 'dart:async';
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:signalr_core/signalr_core.dart';

class SignalRProvider with ChangeNotifier {
    static List<UserMessageModel> messages = List<UserMessageModel>();

    static HubConnection connection = HubConnectionBuilder()
    .withUrl(
      'https://signal.domain.com/chatHub',
      HttpConnectionOptions(
        logging: (level, message) => print(message),
      ))
    .build();

Function(bool update) onMessagesUpdateCallback;

Future initSignalR() async {
    await connection.start();

    connection.on('ReceiveMessage', (message) async {
        print(message);
    if (onMessagesUpdateCallback != null) {
        onMessagesUpdateCallback(true);
  }
});

connection.on("ReceiveConnectedMessage", (message) async {
  print("Connecting...}");
  await connection.invoke('Init', args: [
    'notifApp',
    'mojarab',
    connection.connectionId,
    'notification_app'
  ]);
  print("connected SignalRProvider");
});

connection.on("ReceiveDisconnectedMessage", (message) async {
  print("SignalR disconnected");
  await connection.start();
});

Timer timer = Timer.periodic(Duration(seconds: 10), (timer) async {
  if (connection.state == HubConnectionState.connected) {
    await connection
        .invoke('StayLiveMessage', args: ['mojarab app', 'i am alive']);
    print("I am Alive!");
  } else {
    await connection.start();
  }
});
}
}

this code is for my server side hub service with c# and blazor technology signalR technology

using BI;
using Common.Utilities;
using Data;
using Entities;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace Messaging.Server.Hubs
{
    public class ChatHub : Hub
    {
        private IMessageBusiness messageManager;
        private IUserBusiness userManager;

        public ChatHub(
            IMessageBusiness _messageManager, IUserBusiness _userManager
        )
        {
            messageManager = _messageManager;
            userManager = _userManager; ;
        }

        public async Task Init(string app, string user, string connection, string device)
        {
            await userManager.AddOrUpdateUser(app, user, connection, device, "users");

            await SendUserMessages(app, "", user);
        }

        public async Task StayLiveMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveLiveMessage", user, message);
        }

        public async Task SendMessage(string jsonMessage)
        {
             await Clients.All.SendAsync("ReceiveMessage", jsonMessage);

             await Clients.All.SendAsync("AndroidReceiveMessage", jsonMessage);
        }

        public async Task SendMessageToClient(string jsonMessage)
        {
            Entities.UserMessageModel message = 
                 Newtonsoft.Json.JsonConvert.DeserializeObject<Entities.UserMessageModel> 
                 (jsonMessage);

            var oUser = await userManager.getUser(message.app, message.user, "users");

            await messageManager.AddMessage(message, "messages");

            await SendUserMessages(message.app, message.category, message.user);
        }

        private async Task SendUserMessages(string app, string category, string user)
        {
            var userData = await userManager.getUser(app, user, "users");
            var userNotif = await userManager.getUser("notifApp", user, "users");

            if (userData != null)
            {
                var userMessages = await messageManager.GetMessages(app, user, "messages");

                if (userMessages != null && userMessages.Count() > 0)
                {
                    foreach (var msg in userMessages)
                    {
                        var note = Newtonsoft.Json.JsonConvert.SerializeObject(msg);

                        await Clients
                        .Client(userData.connection)
                        .SendAsync("ReceiveMessage", note);
                    }
                }
            }

            if (userNotif != null)
            {
                 var userMessages = await messageManager.GetAllAppsMessages(user, "messages");

                 if (userMessages != null && userMessages.Count() > 0)
                {
                     foreach (var msg in userMessages)
                     {
                    var note = Newtonsoft.Json.JsonConvert.SerializeObject(msg);

                    await Clients
                        .Client(userNotif.connection)
                        .SendAsync("AndroidReceiveMessage", note);
                }
            }
        }
    }

    public override async Task OnConnectedAsync()
    {
        await Clients.All.SendAsync("ReceiveConnectedMessage", Context.ConnectionId);
    }

    public override async Task OnDisconnectedAsync(Exception exception)
    {
        await userManager.setDisconnectedUser(Context.ConnectionId, "users");

        if (exception != null)
        {
            await Clients.All.SendAsync("ReceiveDisconnectedMessage", Context.ConnectionId + " : " + 
            exception.Message);
        }
        else
        {
            await Clients.All.SendAsync("ReceiveDisconnectedMessage", Context.ConnectionId);
        }
    }
    }
   }

this is error log

I/GED     ( 5022): ged_boost_gpu_freq, level 100, eOrigin 2, final_idx 24, 
oppidx_max 24, oppidx_min 0
I/flutter ( 5022): Starting HubConnection.
I/flutter ( 5022): Starting connection with transfer format 
'TransferFormat.text'.
I/flutter ( 5022): Sending negotiation request: 
https://signal.dinavision.org/chatHub/negotiate.
I/flutter ( 5022): Selecting transport 'HttpTransportType.webSockets'.
I/flutter ( 5022): (WebSockets transport) Connecting.
I/flutter ( 5022): WebSocket connected to 
wss://signal.dinavision.org/chatHub? 
id=3l6Pd4QpcKsTQEy0RnPlIw#.
I/flutter ( 5022): The HttpConnection connected successfully.
I/flutter ( 5022): Sending handshake request.
I/flutter ( 5022): (WebSockets transport) sending data. String data of length 
'32'.
I/flutter ( 5022): Using HubProtocol 'json'.
I/flutter ( 5022): (WebSockets transport) data received. String data of 
length  
'3'
I/flutter ( 5022): Server handshake complete.
I/flutter ( 5022): (WebSockets transport) data received. String data of 
length 
'85'
I/flutter ( 5022): connected : [3l6Pd4QpcKsTQEy0RnPlIw]
I/flutter ( 5022): HubConnection connected successfully.
I/flutter ( 5022): (WebSockets transport) sending data. String data of length 
'115'.
I/flutter ( 5022): (WebSockets transport) socket closed.
I/flutter ( 5022): HttpConnection.stopConnection(null) called while in state 
ConnectionState.connected.
I/flutter ( 5022): Connection disconnected.
I/flutter ( 5022): HubConnection.connectionClosed(null) called while in state 
HubConnectionState.connected.
E/flutter ( 5022): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled 
Exception: Exception: Invocation canceled due to the underlying connection 
being 
closed.
E/flutter ( 5022): 
2 Answers

You should make SignalRProvider a service you can inject, and not use a static variable for the hubconnection.

I found that the asp.net core server side package might be updated to these.

Microsoft.AspNetCore.SignalR.Common": "3.1.0.0",
Microsoft.AspNetCore.SignalR.Core": "1.1.0.0",
Microsoft.AspNetCore.SignalR": "1.1.0.0",
Microsoft.AspNetCore.SignalR.Protocols.Json": "3.1.1.7",
Microsoft.AspNetCore.StaticFiles": "3.1.0.0",
Microsoft.AspNetCore.WebSockets": "2.2.1",
Related