Giter Site home page Giter Site logo

sefidgaran / signalr_client Goto Github PK

View Code? Open in Web Editor NEW

This project forked from soernt/signalr_client

68.0 9.0 110.0 232 KB

A Flutter SignalR Client for ASP.NET Core

Home Page: https://pub.dev/packages/signalr_netcore

License: MIT License

Objective-C 0.04% Dart 95.23% C# 4.12% HTML 0.08% Kotlin 0.13% Swift 0.40%
dart flutter signalr chatclient chatserver csharp aspnetcore

signalr_client's Introduction

signalr_client

pub package

A Flutter SignalR Client for ASP.NET Core.
ASP.NET Core SignalR is an open-source library that simplifies adding real-time web functionality to apps. Real-time web functionality enables server-side code to push content to clients instantly.

Tested with ASP.NET Core 3.1 & ASP .NET Core 6

The client is able to invoke server side hub functions (including streaming functions) and to receive method invocations issued by the server. It also supports the auto-reconnect feature.

The client supports the following transport protocols:

  • WebSocket
  • Service Side Events
  • Long Polling

The client supports the following hub protocols:

  • Json
  • MessagePack

Examples

Getting Started

Add signalr_netcore to your pubspec.yaml dependencies:

...
dependencies:
  flutter:
    sdk: flutter

  signalr_netcore:
...

Important Note: if you are experiencing issues (for example not receiving message callback) with the latest version, please give a try to older version as signalr_netcore: 0.1.7+2-nullsafety.3 but bear in mind that this version does not support auto reconnect functionalities and need to be handled manually.

Usage

Let's demo some basic usages:

1. Create a hub connection:

// Import the library.
import 'package:signalr_netcore/signalr_client.dart';

// The location of the SignalR Server.
final serverUrl = "192.168.10.50:51001";
// Creates the connection by using the HubConnectionBuilder.
final hubConnection = HubConnectionBuilder().withUrl(serverUrl).build();
// When the connection is closed, print out a message to the console.
final hubConnection.onclose( (error) => print("Connection Closed"));

Logging is supported via the dart logging package:

// Import theses libraries.
import 'package:logging/logging.dart';
import 'package:signalr_netcore/signalr_client.dart';

// Configer the logging
Logger.root.level = Level.ALL;
// Writes the log messages to the console
Logger.root.onRecord.listen((LogRecord rec) {
  print('${rec.level.name}: ${rec.time}: ${rec.message}');
});

// If you want only to log out the message for the higer level hub protocol:
final hubProtLogger = Logger("SignalR - hub");
// If youn want to also to log out transport messages:
final transportProtLogger = Logger("SignalR - transport");

// The location of the SignalR Server.
final serverUrl = "192.168.10.50:51001";
final connectionOptions = HttpConnectionOptions
final httpOptions = new HttpConnectionOptions(logger: transportProtLogger);
//final httpOptions = new HttpConnectionOptions(logger: transportProtLogger, transport: HttpTransportType.WebSockets); // default transport type.
//final httpOptions = new HttpConnectionOptions(logger: transportProtLogger, transport: HttpTransportType.ServerSentEvents);
//final httpOptions = new HttpConnectionOptions(logger: transportProtLogger, transport: HttpTransportType.LongPolling);

// If you need to authorize the Hub connection than provide a an async callback function that returns 
// the token string (see AccessTokenFactory typdef) and assigned it to the accessTokenFactory parameter:
// final httpOptions = new HttpConnectionOptions( .... accessTokenFactory: () async => await getAccessToken() ); 

// Creates the connection by using the HubConnectionBuilder.
final hubConnection = HubConnectionBuilder().withUrl(serverUrl, options: httpOptions).configureLogging(hubProtLogger).build();
// When the connection is closed, print out a message to the console.
final hubConnection.onclose( (error) => print("Connection Closed"));

2. Connect to a Hub:

Calling following method starts handshaking and connects the client to SignalR server

await hubConnection.start();

3. Calling a Hub function:

Assuming there is this hub function:

public string MethodOneSimpleParameterSimpleReturnValue(string p1)
{
  Console.WriteLine($"'MethodOneSimpleParameterSimpleReturnValue' invoked. Parameter value: '{p1}");
  return p1;
}

The client can invoke the function by using:

  final result = await hubConnection.invoke("MethodOneSimpleParameterSimpleReturnValue", args: <Object>["ParameterValue"]);
  logger.log(LogLevel.Information, "Result: '$result");

4. Calling a client function:

Assuming the server calls a function "aClientProvidedFunction":

  await Clients.Caller.SendAsync("aClientProvidedFunction", null);

The Client provides the function like this:

  
  hubConnection.on("aClientProvidedFunction", _handleAClientProvidedFunction);

  // To unregister the function use:
  // a) to unregister a specific implementation:
  // hubConnection.off("aClientProvidedFunction", method: _handleServerInvokeMethodNoParametersNoReturnValue);
  // b) to unregister all implementations:
  // hubConnection.off("aClientProvidedFunction");
  ...
  void _handleAClientProvidedFunction(List<Object> parameters) {
    logger.log(LogLevel.Information, "Server invoked the method");
  }

5. Using Msgpack for serialization

The Hub should be configured to use the msgpack protocol in both the client and server

Client

import 'package:signalr_netcore/msgpack_hub_protocol.dart';
_hubConnection = HubConnectionBuilder()
          .withUrl(_serverUrl, options: httpOptions)
          /* Configure the Hub with msgpack protocol */
          .withHubProtocol(MessagePackHubProtocol())
          .withAutomaticReconnect()
          .configureLogging(logger)
          .build();

Server

Add the following packge to your ASP NET core project Microsoft.AspNetCore.SignalR.Protocols.MessagePack

public void ConfigureServices(IServiceCollection services)
        {
            // Configure the hub to use msgpack protocol
            services.AddSignalR().AddMessagePackProtocol();

        }

A note about the parameter types

All function parameters and return values are serialized/deserialized into/from JSON by using the dart:convert package (json.endcode/json.decode). Make sure that you:

  • use only simple parameter types

or

  • use objects that implements toJson() since that method is used by the dart:convert package to serialize an object.

Flutter Json 101:

MSGPACK

All function parameters and return values are serialized/deserialized into/from Msgpack by using the msgpack_dart package. Make sure that you:

  • use only simple parameter types or
  • Convert your classes to maps using Json encode/decode and then pass it to msgpack or
  • Serialize the message into bytes using msgpack_dart using custom encoders and decoders before passing it to signalr

How to expose a MessageHeaders object so the client can send default headers

Code Example:

final defaultHeaders = MessageHeaders();
defaultHeaders.setHeaderValue("HEADER_MOCK_1", "HEADER_VALUE_1");
defaultHeaders.setHeaderValue("HEADER_MOCK_2", "HEADER_VALUE_2");

final httpConnectionOptions = new HttpConnectionOptions(
          httpClient: WebSupportingHttpClient(logger,
              httpClientCreateCallback: _httpClientCreateCallback),
          accessTokenFactory: () => Future.value('JWT_TOKEN'),
          logger: logger,
          logMessageContent: true,
          headers: defaultHeaders);

final _hubConnection = HubConnectionBuilder()
          .withUrl(_serverUrl, options: httpConnectionOptions)
          .withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000, null])
          .configureLogging(logger)
          .build();

Http Request Log:

I/flutter ( 5248): Starting connection with transfer format 'TransferFormat.Text'.
I/flutter ( 5248): Sending negotiation request: https://localhost:5000/negotiate?negotiateVersion=1
I/flutter ( 5248): HTTP send: url 'https://localhost:5000/negotiate?negotiateVersion=1', method: 'POST' content: '' content length = '0' 
headers: '{ content-type: text/plain;charset=UTF-8 }, { HEADER_MOCK_1: HEADER_VALUE_1 }, { X-Requested-With: FlutterHttpClient }, { HEADER_MOCK_2: HEADER_VALUE_2 }, { Authorization: Bearer JWT_TOKEN }'

signalr_client's People

Contributors

chrisdrobison avatar golovin-igor avatar heathhopkins avatar kaashyapan avatar luizrsilva avatar macromania avatar mikeesouth avatar sefidgaran avatar shawnysp avatar soernt avatar svsk417 avatar tvolkert avatar westwoodra2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

signalr_client's Issues

WebSupportingHttpClient: Invalid type cast in log string interpolation

When logging is used, a long-polling connection attempt fails with the following exception:
Failed to start the connection: Unable to connect to the server with any of the available transports. HttpTransportType.LongPolling failed: type 'Null' is not a subtype of type 'String' in type cast

The exception is thrown in the WebSupportingHttpClient class (line 72), when request.content is null, but is casted to String to build the log output text.

Suggestion:
Leave away the content length altogether, because the string content is printed anyways, and the length can easily be extracted.

_logger?.finest(
          "HTTP send: url '${request.url}', method: '${request.method}' content: '${request.content}' headers: '$headers'");

Cannot connect to server

Trying to connect to a dotnet6.0 SignalR server, I'm constantly getting this error in sensor.connect():
Cannot connect to sensor: Invocation canceled due to the underlying connection being closed.
What is the issue? A C# client works like a charm.

main.dart:

import 'dart:io';
import 'sensor.dart';

void showText(String message) {
  print(message);
}

void finished(String message) {
  print(message);
}

Future<void> main() async {
  var sensor = Sensor(showText, finished, reconnect: false);
  try {
    var connected = await sensor.connect();
    var username = await sensor.identify();
    print("identified as ${username}");
    sleep(Duration(milliseconds: 500));
    var population = ["foo", "bar", "boo", "far"];
    var verified = await sensor.verify(username, population);
    print("verified: ${verified}");
  } on SensorException catch (e) {
    print('Cannot connect to sensor: ${e.inner}');
  }
}

sensor.dart:

import 'dart:io';
import 'dart:math';
import 'package:signalr_netcore/signalr_client.dart';

class Sensor {
  late HubConnection connection;
  bool reconnect;
  void Function(String) showText;
  void Function(String) finished;

  Sensor(this.showText, this.finished, {this.reconnect = true})
  {
    var builder = HubConnectionBuilder()
        .withUrl("https://localhost:53354/Sensor");
    if (reconnect)
      builder.withAutomaticReconnect();
    connection = builder.build();
    connection.onclose(({error}) {
      sleep(Duration(milliseconds: Random().nextInt(5) * 1000));
      connection.start();
    });
    if (reconnect) {
      connection.onreconnecting(({error}) {
        assert(connection.state == HubConnectionState.Reconnecting);
        showText("connection to sensor lost, reconnecting...");
      });
      connection.onreconnected(({connectionId}) {
        assert(connection.state == HubConnectionState.Connected);
        showText("reconnected to sensor");
      });
    }
  }

  Future<bool> connect() async {
    connection.on("ShowText", (text) {
      showText(text as String);
    });
    connection.on("Finished", (text) {
      finished(text as String);
    });
    while (true) {
      try {
        await connection.start();
        assert(connection.state == HubConnectionState.Connected);
        return true;
      } on Exception catch(e) {
        throw SensorException(e);
      }
    }
  }

  Future<String> identify({int sensorId = 0}) async {
    try {
      return await connection.invoke("Identify", args: [sensorId]) as String;
    } on Exception catch(e) {
      throw SensorException(e);
    }
  }

  Future<bool> verify(String user, List<String> population, {int sensorId = 0}) async {
    try {
      return await connection.invoke("Verify", args: [user, population, sensorId]) as bool;
    } on Exception catch(e) {
      throw SensorException(e);
    }
  }
}

class SensorException implements Exception {
  Exception inner;
  SensorException(this.inner);
}

TimeoutException after 0:00:02.000000: Future not completed

Dear when i try to connect with server i am getting "TimeoutException after 0:00:02.000000: Future not completed" issue , please check it and if working with you then please advise how can i fix this.

Note: I am using emulator and due to that reason i am accessing the localhost with ip: 10.0.2.2

Server trying to call client method with null parameters crashes the client

The HubConnection will disconnect if my server calls a client method with null parameters. After some digging I found that InvocationMessage does not allow nullable parameters at all. If I change those the definitions of arguments to List<Object?> , it works without any problem. But this would be a breaking change. Can we get this fixed?

SignalR blocking http requests on server

Hello, I have been developing an app for waiters working in restaurants. App uses signalr_netcore for listening to the state of tables from the .net server. But the developer who's developing server-side says that after connection from a mobile phone the server is blocked and can't handle HTTP requests. And blaming my app for blockage. is there any solution to that? or signal isn't meant to work alongside ordinary HTTP requests?

DateTime/DateTimeOffset not supported???

At server, the following structure is serialized:

new Dictionary<string, object> {
  { "string", "Hello" },
  { "dateTime", DateTime.Now() },
};

On client, the response of that invocation is a Map<dynamic, dynamic> with:

{
  "string": "Hello,
  "dateTime": null,
}

The deserializer got a 0xd7 type, then a 0xff subtype (I guess -1 is considered 255), on this method:

dynamic _readExt(int length) {
  final extType = _readUInt8();
  final data = _readBuffer(length);
  return _extDecoder?.decodeObject(extType, data);
}

At that time, _extDecoder was null, so null was returned.

compatibility with http ^1.1.0

Because signalr_netcore 1.3.6 depends on http ^0.13.6 and no versions of signalr_netcore match >1.3.6 <2.0.0, signalr_netcore ^1.3.6 requires http ^0.13.6.
So, because "App Name "depends on both http ^1.1.0 and signalr_netcore ^1.3.6, version solving failed.

Issues with sse_channel

When using Server Sent Events transport there are at least 2 issues caused by underlying implementation of sse_channel

  1. When access token is used it is getting overriden along with any other query parameters causing 401 error. On signalr_client side this error is not handled properly and nothing happens until handshake timeout is triggered in HubConnection.
  2. There are no stop mechanism in sse_channel so when .stop() method is called on instance of HubConnection the underlying sse connection continues to exist and receiving server sent events leading to unwanted behavior.

If anyone encounters same issues I've made a workaround for them in here.

@sefidgaran I'd be glad to help resolving these if you can suggest a solution on how to deal with sse_channel. The package itself seems to be abandoned so I'm not sure if opening PR there would work.

SignalR Log: SEVERE: Failed to start the connection: None of the transports supported by the client are supported by the server.

i am facing this issue in console and cannot connect with hub.

SignalR Log: SEVERE: Failed to start the connection: None of the transports supported by the client are supported by the server.
Error connecting to SignalR hub: None of the transports supported by the client are supported by the server.
Capture

  • i am trying to connect flutter web app to signalr hub but i am facing this issue.

HttpConnection.stopConnection(Unknown) called while in state ConnectionState.Connected.

Launching lib/main.dart on HMA AL00 in debug mode...
Running Gradle task 'assembleDebug'...
✓ Built build/app/outputs/flutter-apk/app-debug.apk.
Installing build/app/outputs/flutter-apk/app.apk...
Debug service listening on ws://127.0.0.1:56868/ZJDHRABsZoM=/ws
Syncing files to device HMA AL00...
I/flutter (14829): Starting HubConnection.
I/flutter (14829): Starting connection with transfer format 'TransferFormat.Text'.
I/flutter (14829): Sending negotiation request: http://api.dev.leshare.com/signalr-hubs/real-time/negotiate?negotiateVersion=1
W/Gralloc3(14829): mapper 3.x is not supported
I/flutter (14829): HTTP send: url 'http://api.dev.leshare.com/signalr-hubs/real-time/negotiate?negotiateVersion=1', method: 'POST' content: '' content length = '0' headers: '{ content-type: text/plain;charset=UTF-8 }, { X-Requested-With: FlutterHttpClient }, { Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjQyM0E1Q0ZEMDFGRDU5MkFGNjc2RTRGMDAwOTY0NDA4IiwidHlwIjoiYXQrand0In0.eyJuYmYiOjE2NzUzMTgyNDMsImV4cCI6MTcwNjg1NDI0MywiaXNzIjoiaHR0cDovL2FwaS5kZXYubGVzaGFyZS5jb20iLCJhdWQiOiJFTUMiLCJjbGllbnRfaWQiOiJFTUNfQXBwIiwic3ViIjoiM2JhODI1ODQtNzM4Ny02MmQyLTk1NzYtM2EwM2VjNjI2NDI4IiwiYXV0aF90aW1lIjoxNjc1MzE4MjQyLCJpZHAiOiJsb2NhbCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2dpdmVubmFtZSI6IuWImOa4ryIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL3N1cm5hbWUiOiLlmLvlmLvlmLvmg7PnnIvnnIsiLCJwaG9uZV9udW1iZXIiOiIxMzY3MDExOTA4NiIsInBob25lX251bWJlcl92ZXJpZmllZCI6IlRydWUiLCJlbWFpbCI6Inpob3VoYWltaW5nQGxleGlheXVuLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjoiVHJ1ZSIsIm5hbWUiOiJkZGRhZG1pbiIsImlhdCI6MTY3NTMxODI
I/HwViewRootImpl(14829): removeInvalidNode jank list is null
I/flutter (14829): Selecting transport 'HttpTransportType.WebSockets'.
I/flutter (14829): (WebSockets transport) Connecting
I/flutter (14829): WebSocket try connecting to 'ws://api.dev.leshare.com/signalr-hubs/real-time?id=L0ebZWKChkZhg6dyudoY_Q'.
I/flutter (14829): WebSocket connected to 'ws://api.dev.leshare.com/signalr-hubs/real-time?id=L0ebZWKChkZhg6dyudoY_Q'.
I/flutter (14829): The HttpConnection connected successfully.
I/flutter (14829): Sending handshake request.
I/flutter (14829): (WebSockets transport) sending data. String data of length 32. Content: '{"protocol":"json","version":1}�'.
I/flutter (14829): Using HubProtocol 'json'.
E/flutter (14829): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: WebSocketException: Connection to 'http://api.dev.leshare.com:0/signalr-hubs/real-time?id=L0ebZWKChkZhg6dyudoY_Q#' was not upgraded to websocket
E/flutter (14829): #0 _WebSocketImpl.connect (dart:_http/websocket_impl.dart:1011:41)
E/flutter (14829): #1 WebSocket.connect (dart:_http/websocket.dart:360:22)
E/flutter (14829): #2 new IOWebSocketChannel.connect (package:web_socket_channel/io.dart:80:28)
E/flutter (14829): #3 connect (package:web_socket_channel/src/_connect_io.dart:15:24)
E/flutter (14829): #4 new WebSocketChannel.connect (package:web_socket_channel/src/channel.dart:115:16)
E/flutter (14829): #5 WebSocketTransport.connect (package:signalr_netcore/web_socket_transport.dart:53:35)
E/flutter (14829): #6 HttpConnection._startTransport (package:signalr_netcore/http_connection.dart:574:24)
E/flutter (14829): #7 HttpConnection._createTransport (package:signalr_netcore/http_connection.dart:529:15)
E/flutter (14829): #8 HttpConnection._startInternal (package:signalr_netcore/http_connection.dart:409:15)
E/flutter (14829):
E/flutter (14829): #9 HttpConnection.start (package:signalr_netcore/http_connection.dart:255:5)
E/flutter (14829):
E/flutter (14829): #10 HubConnection._startInternal (package:signalr_netcore/hub_connection.dart:190:5)
E/flutter (14829):
E/flutter (14829): #11 HubConnection._startWithStateTransitions (package:signalr_netcore/hub_connection.dart:172:7)
E/flutter (14829):
E/flutter (14829): #12 ChatPageViewModel.openChatConnection (package:chatclient/chatPageViewModel.dart:113:7)
E/flutter (14829):
E/flutter (14829):
I/flutter (14829): HttpConnection.stopConnection(Unknown) called while in state ConnectionState.Connected.
I/flutter (14829): Connection disconnected.
I/flutter (14829): HubConnection.connectionClosed(null) called while in state HubConnectionState.Connecting.
I/flutter (14829): Hub handshake failed with error 'The underlying connection was closed before the hub handshake could complete.' during start(). Stopping HubConnection.
I/flutter (14829): Call to HttpConnection.stop(Exception: The underlying connection was closed before the hub handshake could complete.) ignored because the connection is already in the disconnected state.
I/flutter (14829): HubConnection failed to start successfully because of error 'The underlying connection was closed before the hub handshake could complete.'.
E/flutter (14829): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: The underlying connection was closed before the hub handshake could complete.
E/flutter (14829):

Can not connect to a hub that has Authorize property

my dontet project has a hub that requires users to have a valid jwt token, my configuration is

HubConnectionBuilder()
      .withUrl(
        "$_serverUrl/hubName",
        options: HttpConnectionOptions(
            accessTokenFactory: ()=> "",
            logger: Logger("SignalR - transport"),
            requestTimeout: 50000,
            logMessageContent: true,
            )),
      )
      .withHubProtocol(MessagePackHubProtocol())
      .withAutomaticReconnect()
      .configureLogging(Logger("SignalR - hub"))
      .build().connect();

but I am getting the following error.

[log] FINER: 2022-11-16 22:27:07.957328: Selecting transport 'HttpTransportType.WebSockets'.
[log] FINEST: 2022-11-16 22:27:07.957909: (WebSockets transport) Connecting
[log] FINEST: 2022-11-16 22:27:07.958410: WebSocket try connecting to 'wss://653e-185-84-71-75.eu.ngrok.io/game-hub/63752f65ed1cf3b745c01953?id=59-ARneXOIDjkQTO_gUZqg&access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2MzcxMmRiZGU4MjUxZjVkMDJjZTc2YjMiLCJqdGkiOiJaTkp2U1c0N0JyX1hNS29seGxXdDciLCJpYXQiOjE2Njg2Mzg2MjEsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0OjgwMDEiLCJhdWQiOiJodHRwczovL2xvY2FsaG9zdDo0MjAwIiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiYWRtaW4iLCJuYmYiOjE2Njg1NTIyMjEsImV4cCI6MTY2ODYzODYyMX0.WcsLGD_8nF9Yqa0IJOuBAqCUShqCVPC2949G3R359T8'.
[log] INFO: 2022-11-16 22:27:07.959286: WebSocket connected to 'wss://653e-185-84-71-75.eu.ngrok.io/game-hub/63752f65ed1cf3b745c01953?id=59-ARneXOIDjkQTO_gUZqg&access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2MzcxMmRiZGU4MjUxZjVkMDJjZTc2YjMiLCJqdGkiOiJaTkp2U1c0N0JyX1hNS29seGxXdDciLCJpYXQiOjE2Njg2Mzg2MjEsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0OjgwMDEiLCJhdWQiOiJodHRwczovL2xvY2FsaG9zdDo0MjAwIiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiYWRtaW4iLCJuYmYiOjE2Njg1NTIyMjEsImV4cCI6MTY2ODYzODYyMX0.WcsLGD_8nF9Yqa0IJOuBAqCUShqCVPC2949G3R359T8'.
[log] FINER: 2022-11-16 22:27:07.959951: The HttpConnection connected successfully.
[log] FINER: 2022-11-16 22:27:07.960187: Sending handshake request.
[log] FINEST: 2022-11-16 22:27:07.960602: (WebSockets transport) sending data. String data of length 39. Content: '{"protocol":"messagepack","version":1}�'.
[log] INFO: 2022-11-16 22:27:07.960941: Using HubProtocol 'messagepack'.
[log] FINER: 2022-11-16 22:27:08.429657: HttpConnection.stopConnection(Unknown) called while in state ConnectionState.Connected.

I am sure the connection is failing because of the Authorize Attribute, removing the attribute from the hub solves the problem, but I need the authorize tag.

Faced the issue not receiving message callback on the latest version.

Important Note: if you are experiencing issues (for example not receiving message callback) with the latest version, please give a try to older version as signalr_netcore: 0.1.7+2-nullsafety.3 but bear in mind that this version does not support auto reconnect functionalities and need to be handled manually.


Flutter version : 2.8.1
I saw the note on the lib page, I could resolve the issue using the 0.1.7+2-nullsafety.3.

The issue is fixed on the next version?
Thanks.

Connection closed while receiving data

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: ClientException: Connection closed while receiving data, uri=##URL
#0 IOClient.send. (package:http/src/io_client.dart:107:13)
#1 Stream.handleError. (dart:async/stream.dart:923:16)
#2 _HandleErrorStream._handleError (dart:async/stream_pipe.dart:269:17)
#3 _ForwardingStreamSubscription._handleError (dart:async/stream_pipe.dart:157:13)
#4 _HttpClientResponse.listen. (dart:_http/http_impl.dart:719:16)
#5 _RootZone.runBinaryGuarded (dart:async/zone.dart:1606:10)
#6 _BufferingStreamSubscription._sendError.sendError (dart:async/stream_impl.dart:358:15)
#7 _BufferingStreamSubscription._sendError (dart:async/stream_impl.dart:376:7)
#8 _BufferingStreamSubscription._addError (dart:async/stream_impl.dart:280:7)
#9 _ForwardingStreamSubscription._addError (dart:async/stream_pipe.dart:128:11)
#10 _addErrorWithReplacement (dart:async/stream_pipe.dart:176:8)
#11 _HandleErrorStream._handleError (dart:async/stream_pipe.dart:274:11)
#12 _ForwardingStreamSubscription._handleError (dart:async/stream_pipe.dart:157:13)
#13 _RootZone.runBinaryGuarded (dart:async/zone.dart:1606:10)
#14 _BufferingStreamSubscription._sendError.sendError (dart:async/stream_impl.dart:358:15)
#15 _BufferingStreamSubscription._sendError (dart:async/stream_impl.dart:376:7)
#16 _BufferingStreamSubscription._addError (dart:async/stream_impl.dart:280:7)
#17 _SyncStreamControllerDispatch._sendError (dart:async/stream_controller.dart:788:19)
#18 _StreamController._addError (dart:async/stream_controller.dart:666:7)
#19 _StreamController.addError (dart:async/stream_controller.dart:620:5)
#20 _HttpParser._reportBodyError (dart:_http/http_parser.dart:1176:22)
#21 _HttpParser._onDone (dart:_http/http_parser.dart:885:9)
#22 _RootZone.runGuarded (dart:async/zone.dart:1582:10)
#23 _BufferingStreamSubscription._sendDone.sendDone (dart:async/stream_impl.dart:392:13)
#24 _BufferingStreamSubscription._sendDone (dart:async/stream_impl.dart:402:7)
#25 _BufferingStreamSubscription._close (dart:async/stream_impl.dart:291:7)
#26 _SyncStreamControllerDispatch._sendDone (dart:async/stream_controller.dart:792:19)
#27 _StreamController._closeUnchecked (dart:async/stream_controller.dart:647:7)
#28 _StreamController.close (dart:async/stream_controller.dart:640:5)
#29 _Socket._onData (dart:io-patch/socket_patch.dart:2454:21)
#30 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10)
#31 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
#32 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#33 _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:784:19)
#34 _StreamController._add (dart:async/stream_controller.dart:658:7)
#35 _StreamController.add (dart:async/stream_controller.dart:606:5)
#36 new _RawSocket. (dart:io-patch/socket_patch.dart:1943:35)
#37 _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1372:18)
#38 _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
#39 _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)

ERROR: None of the transports supported by the client are supported by the server

Hi,

We're trying to implement this package in our systems ( signalr_netcore: ^1.3.2) , and we receive this error message:
None of the transports supported by the client are supported by the server

I tried to configure all 3 transport types (WebSockets, LongPolling, ServerSentEvents) yet this error keeps showing.

Can it be related to the fact that our server use server protocol 1.5?

These are the packages we use on our server side:
Microsoft.AspNet.SignalR.Core version: 2.2.0 framework: net45
Microsoft.AspNet.SignalR.systemWeb version: 2.2.0 framework: net45

What are we missing or what else can we try?

Thanks in advance.
Shlo

Does reconnect feature works when backend restarts ?

First, thank you very much for this package.

I have an issue when I restart my backend and the package's reconnection process occurs.
My client logs shows :

  • pings from server
  • connection to server lost
  • reconnection loop
  • connected with new connection id
  • pings from server

Then even if it seams the reconnection did work as expected, I get a 'Connection timed out' from _ClientSocketException in ioclient.dart from package's http package after trying to asynchronously call the /negociate endpoint.

I tried to implement the reconnection myself but the same issue occurs.

Is this something I should handle in a particular way ?

Thanks in advance for any advise.

WebSockets transport: error calling onReceive, error: type 'List<dynamic>' is not a subtype of type 'List<Object>?'

Hi, I can reproduce the issue

Server code (dotnet core 3.1):

 await Clients.Caller.SendAsync("someMessage", JsonConvert.SerializeObject(new
          {
                some_data= id.ToString(),
                some_other_data = somethingElse.ToString()
          }));

Client code:

import 'package:signalr_netcore/signalr_client.dart';

//all logs are enabled
Logger.root.level = Level.ALL;

Logger.root.onRecord.listen((record) {
      print('${record.level.name}: ${record.time}: ${record.message}');
    });

//specify hub connection options
final httpConnectionOptions = new HttpConnectionOptions(
          accessTokenFactory: () async => await getUserToken(),
          logger: transportProtLogger,
          httpClient: WebSupportingHttpClient(null,
              httpClientCreateCallback: _httpClientCreateCallback),
          logMessageContent: true);


//build the hub connection
final hubConnection = HubConnectionBuilder()
               .withUrl(mainServer + '/myHub', options: httpConnectionOptions)
               .configureLogging(hubProtLogger)
               .withAutomaticReconnect(
                    retryDelays: [2000, 5000, 10000, 20000, 50000]).build();

//...

 _hubConnection.on('someMessage', _handleSomeMessage);

//...


 void _handleSomeMessage(List<Object>? args) {
//This would never call, due to the following error in the logs:
2I/flutter (11935): SEVERE: 2021-10-09 00:33:20.786183: (WebSockets transport) error calling onReceive, error: type 'List<dynamic>' is not a subtype of type 'List<Object>?'

}

After some digging I figured out that error goes from JsonHubProtocol class where invocation message got parsed, e.g. :
signalr_core\json_hub_protocol.dart

class JsonHubProtocol implements IHubProtocol {

//....

static InvocationMessage _getInvocationMessageFromJson(
      Map<String, dynamic> jsonData) {
    final MessageHeaders? headers =
        createMessageHeadersFromJson(jsonData["headers"]);
    final message = InvocationMessage(
        jsonData["target"],

//Here jsonData produces List<dynamic> instead of List<Object>
        jsonData["arguments"],

        jsonData["streamIds"],
        headers,
        jsonData["invocationId"]);

    _assertNotEmptyString(
        message.target, "Invalid payload for Invocation message.");
    if (message.invocationId != null) {
      _assertNotEmptyString(
          message.invocationId, "Invalid payload for Invocation message.");
    }

    return message;
  }

So possible fix would be just add a cast to Object:

        jsonData["arguments"]?.cast<Object>().toList(),

Is package supports Azure SignalR Service?

Hi. I'm trying to connect to azure SignalR service but I got a 401 error. I made azure network public but I'm not sure what is wrong. I successfully connected the self-hosted SignalR. Any help or ideas?

HubConnectionBuilder not passing Message headers to Server Hub

When configuring HubConnectionBuilder().withUrl options headers. The headers are not been pass to the server hub.

My Code:

final headers = MessageHeaders();
headers.setHeaderValue("MyHeader-One", "MY-VALUE1");
headers.setHeaderValue("MyHeader-Two", "MY-VALUE2");

hubConnection = HubConnectionBuilder()
.withUrl(
serverUrl,
options: HttpConnectionOptions(
headers: headers,
transport: HttpTransportType.LongPolling,
),
)
.withAutomaticReconnect()
.build();

Header MyHeader-One and MyHeader-Two are not been received at Hub

Package not working with ssl api

I'm working well with localhost applications, but when i connect to https url i gave error like this.

Here is log.
I/flutter (13925): Starting HubConnection.
I/flutter (13925): Starting connection with transfer format 'TransferFormat.text'.
I/flutter (13925): Sending negotiation request: https://url:2600/notify/negotiate.
I/flutter (13925): Selecting transport 'HttpTransportType.serverSentEvents'.
I/flutter (13925): (SSE transport) Connecting.
I/flutter (13925): SSE connected to https://url:2600/notify?id=UvR4grgdVXNVH0cd4-Wqzw&access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9zeXN0ZW0iOiIxZDMyZGUwYi02MzQ5LTQzNGYtZmMxZi0wOGRhMTNlZjc0NjUiLCJuYW1laWQiOiIzNmYwYjcyOC01NjA4LTQ3MGItYjQ1ZS0zMWI1YjY4YTA0MTUiLCJuYmYiOjE2NTI0NDgzMjgsImV4cCI6MTY1NTA0MDMyOCwiaWF0IjoxNjUyNDQ4MzI4fQ.1nsEoT33fdsV00Mrukq963YGwGsgM4xUtH6CHS1oPKw
I/flutter (13925): The HttpConnection connected successfully.
I/flutter (13925): Sending handshake request.
I/flutter (13925): (SSE transport) sending data. String data of length '32'.
I/flutter (13925): (SSE transport) request complete. Response status: 200.
I/flutter (13925): Using HubProtocol 'json'.
I/flutter (13925): HttpConnection.stopConnection(Exception: Failed to connect to https://url:2600/notify?id=UvR4grgdVXNVH0cd4-Wqzw) called while in state ConnectionState.connected.
I/flutter (13925): Connection disconnected with error 'Exception: Failed to connect to https://url:2600/notify?id=UvR4grgdVXNVH0cd4-Wqzw'.
I/flutter (13925): HubConnection.connectionClosed(Exception: Failed to connect to https://url:2600/notify?id=UvR4grgdVXNVH0cd4-Wqzw) called while in state HubConnectionState.connecting.
I/flutter (13925): Hub handshake failed with error 'Exception: Failed to connect to https://url:2600/notify?id=UvR4grgdVXNVH0cd4-Wqzw' during start(). Stopping HubConnection.
I/flutter (13925): Call to HttpConnection.stop(Exception: Failed to connect to https://url:2600/notify?id=UvR4grgdVXNVH0cd4-Wqzw) ignored because the connection is already in the disconnected state.
I/flutter (13925): HubConnection failed to start successfully because of error '{Exception: Failed to connect to https://url:2600/notify?id=UvR4grgdVXNVH0cd4-Wqzw.toString()}'.
E/flutter (13925): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: Exception: Failed to connect to https://url:2600/notify?id=UvR4grgdVXNVH0cd4-Wqzw
E/flutter (13925):

Web support

While trying to initiate the connection with the server I'm getting this next error.

Error: Unsupported operation: Platform._version at Object.throw_ [as throw] (http://localhost:54573/dart_sdk.js:5348:11) at Function._version (http://localhost:54573/dart_sdk.js:56583:17) at Function.get version [as version] (http://localhost:54573/dart_sdk.js:56657:27) at get _version (http://localhost:54573/dart_sdk.js:56527:27) at Function.desc.get [as _version] (http://localhost:54573/dart_sdk.js:5853:17) at Function.get version [as version] (http://localhost:54573/dart_sdk.js:56501:26) at Object._getHttpVersion (http://localhost:54573/dart_sdk.js:200676:31) at new _http._HttpClient.new (http://localhost:54573/dart_sdk.js:195641:28) at main.MyHttpOverrides.new.createHttpClient (http://localhost:54573/dart_sdk.js:198667:14) at main.MyHttpOverrides.new.createHttpClient (http://localhost:54573/packages/globalnewswebapp/main.dart.lib.js:203:26) at Function.new (http://localhost:54573/dart_sdk.js:189717:24) at dartio_http_client.DartIOHttpClient.new.<anonymous> (http://localhost:54573/packages/signalr_netcore/json_hub_protocol.dart.lib.js:1914:46) at Generator.next (<anonymous>) at runBody (http://localhost:54573/dart_sdk.js:39250:34) at Object._async [as async] (http://localhost:54573/dart_sdk.js:39281:7) at http://localhost:54573/packages/signalr_netcore/json_hub_protocol.dart.lib.js:1911:71 at http://localhost:54573/dart_sdk.js:33560:31 at internalCallback (http://localhost:54573/dart_sdk.js:25311:11)

How can I fix this? I have been googling this and seems an http issue when developing a web app with flutter only.

invoke upload progress feature

When calling the connection.invoke, adding a onProgressCallBack would be nice.

Common usages: indicating image upload progress in chat apps

I could help implement this feature.

Build failed due to use of deprecated Android v1 embedding.

Getting this error when trying to build with Flutter version 2.10.1

Warning
──────────────────────────────────────────────────────────────────────────────
Your Flutter application is created using an older version of the Android
embedding. It is being deprecated in favor of Android embedding v2. Follow the
steps at

https://flutter.dev/go/android-project-migration

to migrate your project. You may also pass the --ignore-deprecation flag to
ignore this check and continue with the deprecated v1 embedding. However,
the v1 Android embedding will be removed in future versions of Flutter.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

TimeoutException after 0:00:10.000000: Future not completed

Getting issue while try to connect socket

 HubConnection hubConnection = HubConnectionBuilder().withUrl("${ServerURL}/chat?userId=$userId", options: HttpConnectionOptions(requestTimeout: 10000)).withAutomaticReconnect().build();
        await hubConnection.start();

.NET Core 5

hello dear

are you have plan to support .NET Core SignalR version 5 ?

thank you

conflict with http package

There is a version conflict between the signalr_netcore and http packages, which prevents successful dependency resolution. Consequently, attempting to install or update packages results in a version-solving failure with the following error message:

Because signalr_netcore >=1.2.0 depends on http ^0.13.3 and PROJECT depends on http 1.1.0, signalr_netcore >=1.2.0 is forbidden. So, because PROJECT depends on signalr_netcore 1.3.4, version solving failed.

BUG: Unhandled exception: type '_HashMap<String, String?>' is not a subtype of type 'Map<String, String>?'

Unhandled exception: type '_HashMap<String, String?>' is not a subtype of type 'Map<String, String>?' in type cast #0 WebSupportingHttpClient._sendHttpRequest (package:signalr_netcore/web_supporting_http_client.dart:125:36) #1 WebSupportingHttpClient.send. (package:signalr_netcore/web_supporting_http_client.dart:79:12) #2 WebSupportingHttpClient.send. (package:signalr_netcore/web_supporting_http_client.dart:38:40) #3 new Future. (dart:async/future.dart:174:37) #4 Timer._createTimer. (dart:async-patch/timer_patch.dart:18:15) #5 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:395:19) #6 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:426:5) #7 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)

Possible error in HubConnection._connectionClosed

While browsing over the source code I've found this bit in HubConnection._connectionClosed method (line 692):

  if (_connectionState == HubConnectionState.Disconnecting) {
    _completeClose(error: error);
  } else if (_connectionState == HubConnectionState.Connected) {
    _reconnect(error: error);
  } else if (_connectionState == HubConnectionState.Connected) {
    _completeClose(error: error);
  }

The last two if conditions are the same.

Failed to complete negotiation with the server: TimeoutException after 0:00:02.000000: Future not completed Dart

Hi, thanks you for such great package.

I am struggiling with this error - SEVERE: 2022-08-16 16:01:01.915620: Failed to complete negotiation with the server: TimeoutException after 0:00:02.000000: Future not completed

If there any chance to prevent it? I get a big pile of data and I don't want my websocket connection to fail and I need to wait until it is all done. As I understand it is not a backend issue (or may be I am wrong, I have searched a lot about this problem but any solutions dosen't work in my case).

My code is like that:

 Future<List> fetchAllBugStuff() async {
    Logger.root.level = Level.ALL;
    Logger.root.onRecord.listen((LogRecord rec) {
      print('${rec.level.name}: ${rec.time}: ${rec.message}');
    });

    final transportProtLogger = Logger("SignalR - transport");

    Logger? logger;

    final httpConnectionOptions = HttpConnectionOptions(
      accessTokenFactory: () => SharedPreferenceService().loginWithToken(),
      headers: defaultHeaders,
      logger: transportProtLogger,
      logMessageContent: true,
    );

    final hubConnection = HubConnectionBuilder()
        .withUrl(
          'http://10.10/home',
          options: httpConnectionOptions,
        )
        .build();
    await hubConnection.start();
    List fixation = [];
    if (hubConnection.state == HubConnectionState.Connected) {
      await hubConnection
          .invoke('GetAllBigStuff')
          .then((value) => fixation = value as List);
      
    }
    hubConnection.keepAliveIntervalInMilliseconds = 10 * 60 * 60 * 1000;
    hubConnection.onclose(({error}) {
      Logger.root.level = Level.SHOUT;
      Logger.root.onRecord.listen((LogRecord rec) {
        print('${rec.level.name}: ${rec.error}: ${rec.message}');
      });
      logger?.finer(error);
    });
    // print(fixation);
    return fixation;
  }

Thanks you for your replying :)

Establish multiple hub connections and get response in parallel

I need to get parallel responses using signalR while uploading my documents. I began connecting hubs one by one. The first hub connection is receiving responses from signalR. Once the next hub connection is established, the previously established connections are no longer receiving responses, even though, the first connection was not closed. The connection got closed if completed or any error occurred. Kindly guide us in establishing a parallel hub connection and receiving responses in parallel.

Here's some code from what I tried.
`

 List<Future> uploadApi = [];

 Future<void> uploadMultipleDocuments(List<Files> files) async {
  for (final element in event.files) {

 // Created a unique channelId for each document.
 final String uploadChannelId=_getChannelId();

 await _establishSignalRConnection(uploadChannelId, element.name);

  // After this API request, will receive data.
 uploadApi.add(_Repository.uploadDocuments());        
   }
   Future.wait(uploadApi);
 }

 Future<void> _establishSignalRConnection(String uploadChannelId, String fileName) async{
  if (hubconnection == null ||
     hubconnection.state == HubConnectionState.Disconnected) {
   await _initializeSignalR(uploadChannelId);
 }

 hubconnection.on(
  uploadChannelId,
   _uploadProgress,
       );
   }

 Future<void> _initializeSignalR(String uploadChannelId) async {
   // Configer the logging
   Logger.root.level = Level.ALL;
   final hubProtLogger = Logger('SignalR - hub');
   final transportProtLogger = Logger('SignalR - transport');

   final String cookie = 'my cookies here';

    final MessageHeaders defaultHeaders = MessageHeaders();
    //Added the headers here with cookies and other requried data.


     hubconnection = HubConnectionBuilder()
    .withUrl(myUrl,
        options: HttpConnectionOptions(
            headers: defaultHeaders,
            logger: transportProtLogger,
            requestTimeout: 3000))
    .configureLogging(hubProtLogger)
    .withAutomaticReconnect(
   retryDelays: [1000, 3000, 3000, 3000],
     ).build();

   hubconnection.onclose(
   ({error}) {
     print('[UploadSignalR]: $error');
   },
 );
    await hubconnection.start();
      }


  void _uploadProgress(List<Object> arg){ 
       //Obtained the percentage from the data received.
   final int finalPercentage = _getProgressPercentage(message);
     print('Channel ID : $uploadChannelId Current Percentage : $finalPercentage')

     if (message.toString().contains('Completed')) {
   _closeSignalRConnection(uploadChannelId);
         }     
 }

`

Incompatibility with http 1.1.0

Hi there,
After upgrading the http package to http 1.1.0, the latest version of your plugin doesn't work, and it's not compatible with it. Can you please fix the issue and make it work with the latest version of the http package?

Handle Lists from backend

Hi, how can I handle lists from the backend.
I have a List of string and I want to parse to dart objects.

The backend consists of returning a list of strings

 private static readonly Dictionary<string, string> userLookup = new();
 await Clients.All.SendAsync(
   Messages.USER.JOINED,
   JsonConvert.SerializeObject(userLookup.Select(x => x.Value)));

The frontend

 hubHelper.hubConnection.on('USER_JOINED', (args) {
    var response = args![0]! as List<String>;
    print(response);
  });
image

I can do the trim, but it's not supposed to deserialize the object into a List in dart?

HubConnection is not working after certain time.

Hello Dear,
We used HubConnection in the Order system in Our Kitchen. But, We are not getting orders after a certain time. Sometimes it won't work after 1 hour on Our Android Devices.

We used Reconnect Feature also. But, no outcomes.

Bug: `_HashMap<String, String?> is not a subtype of type Map<String, String>?`

Unhandled exception: type '_HashMap<String, String?>' is not a subtype of type 'Map<String, String>?' in type cast #0 WebSupportingHttpClient._sendHttpRequest (package:signalr_netcore/web_supporting_http_client.dart:125:36) #1 WebSupportingHttpClient.send.<anonymous closure> (package:signalr_netcore/web_supporting_http_client.dart:79:12) #2 WebSupportingHttpClient.send.<anonymous closure> (package:signalr_netcore/web_supporting_http_client.dart:38:40) #3 new Future.<anonymous closure> (dart:async/future.dart:174:37) #4 Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18:15) #5 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:395:19) #6 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:426:5) #7 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.