GraphQL with .Net Core & Xamarin

GraphQL with .Net Core & Xamarin

For quite some time, people in the JavaScript/React community have been using a mythical query language called “GraphQL”. Some of these developers were claiming it would change the world and that it would mean the end of RESTFul APIs. Only recently, people from the .NET community started to adopt this mysterious query language. One of these people was Brandon Minnick, who also inspired me to learn more about GraphQL.

In a series of blog posts, I will take you on a journey to the world of GraphQL for .NET. This first blog post will cover the basics of GraphQL and why You would want to use it. In the following blog posts I will elaborate on how to build a GraphQL endpoint with .NET Core 3, and how to consume GraphQL in a Xamarin app. See you on the other side!

Back in 2012, Facebook decided it was time to rebuild their apps. The existing apps were sluggish and crashing all the time. The main cause was that Facebook became more complex and the app was making way too many API calls to get the data. Optimizing and caching could improve performance, but with Facebook evolving, they would eventually run into these issues again. Developers at Facebook started to rethink their data fetching strategy and that’s when GraphQL was born. A few years later, in 2015, the GraphQL spec was open-sourced and nowadays is maintained by The GraphQL Foundation.

What is GraphQL?

GraphQL can be best described as a (specification for) a JSON-like query language for API’s. With these queries, the client has control over what data is returned by the API. This is in contrast to REST, where the API defines the request and response. Another big difference between other types of API’s, is that GraphQL only has one endpoint. This endpoint exposes a schema that describes what data types (Queries) can be used by the client. In addition to the data types, it also exposes the operations that can be performed. Basically, the operations can be divided into 3 categories: Queries, Mutations & Subscriptions. These categories are key concepts of GraphQL, so let’s have a closer look!

Queries

The idea behind GraphQL was to build an API that clients can use to consume data efficiently, and that’s exactly what Queries allow you to do. Only the data types that are exposed through a query, can be used by the client. When using a query, the client can ask for a set of fields instead of getting all the fields from that type. This allows for requests to be way more efficient.

When a data type references other data types (nested type), you can fetch these as well (still using one query). Even if there is not a specific query exposing this type.

Example:
Let’s say we want to rebuild the GitHub User profile page. With REST you would probably need to make a few HTTP requests to collect data about the User, Repositories, Followers, etc.. With GraphQL you can get all this from the User query, in a single HTTP call:

Request

query
{
  user(login: "basdecort") {
    name
    repositories(first: 10) {
      nodes {
        name
        createdAt
      }
    }
    followers(first: 100) {
      nodes {
        name
      }
    }
  }
}

Response

{
  "data": {
    "user": {
      "name": "Bas de Cort",
      "repositories": {
        "nodes": [
        {
            "name": "Xamarin",
            "createdAt": "2017-11-02T14:20:34Z"
        }]
      },
      "followers": {
        "nodes": [{"name": "Follower 1"}]
      }
    }
  }
}

* On the first level the Query provides a filter on the User query to only get the user with loginname "basdecort". On the second level, it's specifying the fields it wants to receive (name, repositories, followers). On the final level, it describes what range (first:10) and what fields of the repositories/followers (nested types) it wants to receive.

Mutations

With mutations the client can add, edit or delete data. Only the mutations that are exposed by the schema can be used to modify data. If there is no mutation in the GraphQL schema, the client is not able to manipulate data in the API.

Example:
Building on top of the previous example, it would be a great addition to allow the user to update his/her User status. This is where a Mutation comes into play. By exposing a "ChangeUserStatus" mutation in your GraphQL schema, the client can update the status through this Mutation.

Request

mutation changeUserStatus
{
  changeUserStatus(input:
    {
      message: "Testing GraphQL"
    })
  {
    status
    {
      message,
      createdAt
    }
  }
}
Response

{
  "data": {
    "changeUserStatus": 
    {
      "status": 
      {
        "message": "Testing GraphQL",
        "createdAt": "2019-10-10T19:55:35Z"
      }
    }
  }
}


* The first row describes that it wants to execute this specific Mutation. After that, it passes the input for the Mutation, in this case, the new status update. On the deepest level, it's describing what values the client needs in the response (message and createdAt for Status).

Subscriptions

The newest feature of GraphQL (at this time of writing) is called Subscriptions. This allows a client to get notified about events that are happening. With the growth of event-driven architectures, this can be a pretty powerful feature. To get (near) real-time notifications, WebSockets are used as a protocol.

Example:
As mentioned, subscriptions are a great way to get notified about changes in the API. When looking at previous examples based on GitHub, notifications of comments on a Pull Request would be a great use case. When a client subscribes for this type of event (new comment event), the API will send a notification using WebSockets when a comment is posted.

Request

subscription
{
  newCommentEvent(pullReqId: "123456")
  {
    id,
    message
  }
}
Response (when a comment is posted)

{
  "newCommentEvent": 
  {
    "id": "8b4dff0e",
    "message": "OK to merge!"
  }
}

* On the third row of this example, the client is subscribing to the "newCommentEvent" subscription. The client will only receive notifications about comments that are made on a PR that matches the filter (pullReqId: "123456"). Finally, just like previous examples, it specifies what fields it wants in return.


The Query and Mutation in the sample above can be executed on the GraphQL endpoint from GitHub. If you want to give it a try, the GraphQL API Explorer is a great way to experiment with the GraphQL Query language. Unfortunately, subscriptions are not (yet) supported by the GitHub endpoint.

https://www.deviantart.com/acakadut/art/Superman-s-Weakness-478899398

Strengths & weaknesses

Just like all great things (and heroes), GraphQL also has its weaknesses. To decide if GraphQL suits your needs, it's important to see if the benefits outweigh the disadvantages in comparison to other architectures like REST. The list below contains some strengths and weaknesses, that hopefully will help you decide if this is for you:

Strengths of GraphQL

  • Built for mobile; GraphQL was designed to match the needs of (mobile) client applications. The flexibility of a GraphQL endpoint really empowers front-end developers to get the most out of their work.
  • Version-free; According to many people, the fact that GraphQL doesn't need versioning is a big advantage. As long as you don't remove fields from the types, the clients won't break. This is not very unique, if you think this through, this can also be achieved with other architectures.
  • A single endpoint; There is only one endpoint, which makes it less complicated to navigate the API.
  • Less requests & smaller bandwidth; where an application normally would have to make a few API calls to fetch data, with GraphQL you can get this information in a single API call. On top of that, GraphQL also allows you to specify what fields you need (instead of returning all the fields for a type). With this, you can save a lot of bandwidth and resource usage (like battery) of the client. Awesome!
  • Couple with any source; It doesn't matter where the data in your GraphQL endpoint is coming from. The data source can be different for each field (!) in your types. You can even build a GraphQL endpoint on top of an existing API.
  • Authorization on fields; Based on the authentication details provided by the client, you are able to expose a limited set of fields (on your types). This is also possible with other architectures, but this would probably get complex pretty fast. The way GraphQL endpoints are architected makes it easier to implement authorization per field.
  • Control over API; This is probably not a benefit compared to other ways of architecting your API, but an important thing to notice. Although clients have a lot of control in making requests, there are still a lot of ways to enforce rules on your GraphQL API. For example: to guarantee performance, the client can only fetch a number of items at once (pagination).
  • Self-documenting; Just like Swagger is generating UI and documentation for a REST API, GraphiQL will generate documentation for your GraphQL endpoint. It also has a Playground that allows you to test your queries.  

Weaknesses of GraphQL

  • No caching; Because all requests to a GraphQL endpoint are POST requests, a lot of web applications don't support caching. Most of them only support the caching of GET requests.
  • More difficult to optimize; The client has a lot of flexibility to request what it needs. Because the API may get a lot of different requests, it's more difficult to optimize the performance.
  • Not suitable for returning files; Although it might be possible to return (Base64 encoded for example) files, this is not recommended. If this is required, it's probably best to return a URL to the file (hosted somewhere else).
  • Still pretty new (for .NET); As mentioned before, GraphQL is pretty new in the .NET community. As a result, libraries might still have some issues and it can be harder to find information online.

I've only built a few GraphQL endpoints, mostly as a Proof Of Concept. I would love to hear from developers with experience in real-world projects. Please feel free to reach out in the comments below, or on Twitter.

What's next?

Hopefully, this article gives a good impression of what GraphQL can do. In the following blog post I will cover the technical bits of implementing a GraphQL endpoint with .NET Core 3.0. If you cannot wait to get your hands on this cool stuff, I recommend this video from Brandon Minnick and the course on LinkedIn Learning from Glenn Block.

Bas de Cort

About Bas de Cort

Bas is a software developer from The Netherlands with a great passion for mobile and innovative technology. This blog will mostly cover mobile technology, especially Xamarin.

Comments