Tanka GraphQL Client for .NET standard released

Tanka GraphQL Client for .NET standard released

Chat demo applications
Chat demo apps using real-time communication with SignalR

My friend Pekka Heikura released his Tanka GraphQL execution library for SignalR based servers. This includes streaming support using SignalR hubs and Apollo link for that as well. I ended up writing a simple .NET standard client library to handle the communication between native applications and the server using HubConnection.

You can pick up source code from Tanka GraphQL .NET Client repository or get the latest releases from NuGet.

Features

  • Execute queries, mutations and subsriptions using SignalR HubConnection
  • Supports GraphQL validation and tracing
  • Leverage power of SignalR communication techniques (WebSockets, Server-Sent Events, Long Polling)

API usage

When staring to work with the API, remember to add correct using statement.

using Tanka.GraphQL;

Connecting to the server

Since the implementation is built on top of the normal SignalR functionality, you will connect to the server using regular SignalR HubConnection. If you are new to the SignalR, see the documentation for more information.

var connection = new HubConnectionBuilder()
                    .WithUrl("https://localhost:5000/hubs/graphql")
                    .Build();
await connection.StartAsync();

Defining models

You need to define your DTOs as POCOs which are used to serialise the data.

public class Message
{
    public int Id { get; set; }
    public string Content { get; set; }
}

public class InputMessage
{
    public string Content { get; set; }
}

Queries and mutations

In GraphQL both queries and mutations are defined as queries so they are handled the same way in the API.

Executing queries are done using HubConnection.QueryAsync method which is an extension method that takes a QueryRequest as a parameter and sends that to the server and returns ExecutionResult after the response is returned. QueryResult defines the GraphQL query and possible parameters (variables).

The easiest way to get the data out from the result is to use GetDataFieldAs<T>-method which either takes the first returned data item or alternatively you can ask a specific item using GetDataFieldAs<T>(string). Errors are returned as part of the ExecutionResult as well so remember to check if there were any.

var channelId = 1;
var channelMessageGQL = @"query Messages($channelId: Int!) {
                messages(channelId: $channelId) {
                  id
                  content
                }
            }";

var queryRequest = new QueryRequest()
{
    Query = channelMessageGQL,
    Variables = new Dictionary<string, object>()
        {
            { "channelId", channelId }
        }
};

var result = await connection.QueryAsync(queryRequest);
var data = result.GetDataFieldAs<List<Message>>();
var postMessageMutationGQL = @"mutation PostMessage($channelId: Int!, $message: InputMessage) {
               postMessage(channelId: $channelId, message: $message) {
                 id
                 content
               }
            }";

var queryRequest = new QueryRequest()
{
    Query = postMessageMutationGQL,
    Variables = new Dictionary<string, object>()
        {
            { "channelId", channelId },
            { "message", new InputMessage() { Content = message } }
        }
};

var result = await connection.QueryAsync(queryRequest);
var data = result.GetDataFieldAs<Messages>();

Subscriptions

API provides support for subscriptions as streams using IObservable<ExecutionResult> and you can use Subscribe method subscripe to the stream.

var channelSubsribtionGQL = 
           @"subscription MessageAdded($channelId: Int!) {
                messageAdded(channelId: $channelId) {
                  id
                  content
                }
            }";

var queryRequest = new QueryRequest()
{
    Query = channelSubsribtionGQL,
    Variables = new Dictionary<string, object>()
        {
            { "channelId", channelId}
        }
};

var subscriptionSource = new CancellationTokenSource();
var serverSubscription = await connection.SubscribeAsync(request, subscriptionSource);
serverSubscription.Subscribe(
                result =>
                {
                    var message = result.GetDataFieldAs<Message>();
                    // Handle new message added
                });               

Summary

GraphQL is the new kid on the block that everyone is raving about. It definitely has some really cool features and is worth looking into if you haven’t had a chance to do so. I hope that this library will make your life a bit easier on this road.

Links

Leave a Reply