Tech Writers

GraphQL in dotNET applications

9 minutes

In this article I will talk about GraphQL with a focus on dotNet applications. Here, I will show how inherent problems of REST motivated the creation of GraphQL. Next, I will present the basic concepts of the specification of this language. Afterwards, I will present the Hot Chocolate library, which is one of many libraries that implement the GraphQL specification. Finally, I will show a small example of using this library in a dotNet application. 

REST

Before we talk about GraphQL, it is necessary to talk about REST. The term was coined by Roy Thomas Fielding (2000) in his doctoral thesis. In this work, Fielding presents REST as an architectural pattern for web applications defined by five constraints: 

  • Client-server: This restriction defines that the user interface must be separated from the system components that process and store data. 
  • Stateless: This restriction says that the client does not need to be aware of the server's state, nor does the server need to be aware of the client's state. 
  • Cache: This restriction indicates that, when possible, the server application must indicate to the client application that data can be cached. 
  • Layered system: This restriction indicates that the application must be built by stacking layers that add functionality to each other. 
  • Uniforminterface: This restriction indicates that the application's resources must be made available in a uniform manner, so that, when learning how to access one resource, one automatically knows how to access the others. According to Fielding's work, this is one of the central characteristics that distinguish REST from other architectural patterns. However, the author himself states that this degrades the efficiency of the application, as resources are not made available in a way that meets the specific needs of a given application. 

What REST looks like in practice

In Figure 1 you can see part of Microsoft's OneDrive API. In this image you can see the uniformity in access to resources. This is noticeable when we notice that, to obtain data, simply send a GET request to an endpoint that starts with the term drive and is followed by the name of the resource and its ID. The same logic applies to creating resources (POST), modifying resources (PUT) and removing them (DELETE). 

Accessing the documentation Google Drive, we can see the typical return of a REST API. The aforementioned documentation shows the large volume of data that a single REST request can bring. Despite being large, a client application may still need to make extra requests to obtain more data about the owner of a file, for example. 

Considering the restrictions determined by Fielding and the examples shown, it is easy to see two problems inherent to REST. The first of these is the data traffic that the consumer does not need and the second is the possible need to make several requests to obtain the data necessary to create a web page. 

Figure 1 - Access the full article here.

Understanding GraphQL

GraphQL emerged in 2012 on Facebook as a solution to problems found in the REST pattern. In 2015, the language became open source and in 2018 the GraphQL Foundation was created, which became responsible for specifying the technology. 

It is important to highlight that GraphQL is not a library or tool. Like SQL, GraphQL is a language for searching and manipulating data. While we use SQL in the database, GraphQL is used in APIs.

Table 1 shows an SQL expression to retrieve an order number and customer name from a database. Similarly, Table 2 shows a GraphQL expression to obtain the same data from an API that supports GraphQL. In the examples, we can see two major advantages of GraphQL over REST. The first is present in the fact that GraphQL allows the consumer to search only for the data they need to create their web page. The second is present in the fact that the consumer could search for order and customer data in a single call. 

Table 1: Example of a select in a relational database. 
Table 2: Example of a GraphQL expression.

I consider it interesting to mention two more characteristics of a GraphQL API. The first of these is the existence of a single endpoint. Unlike REST, where an endpoint is created for each resource, in a GraphQL API all queries and mutations are sent to the same endpoint.  

The second is the fact that a GraphQL API only supports the POST verb. This is yet another difference in relation to a REST, where different HTTP verbs must be used depending on the intention of the request. Therefore, while in a REST API we must use the GET, POST, PUT and DELETE verbs, in a GraphSQL API we will use the POST verb to get, create, change and remove data.  

Schema Definition Language

Let's now talk a little about SDL (Schema Definition Language). When using a relational database, it is first necessary to define the database schema, that is, it is necessary to define the tables, columns and relationships. Something similar happens with GraphQL, that is, the API needs to define a schema so that consumers can search the data. To create this schema, SDL is used.  

The official GraphQL website has a section dedicated to SDL. In that section you can find a complete description of the language for creating GraphQL schemas. In this text, I will present the basic syntax for creating a GraphQL schema. In Figure 2 you can see part of a GraphQL schema created using the Apollo. We can see that the scheme begins with the definition of two fundamental types: Query and Mutation. In the first type we define all the queries that our API will have. In our example, consumers will be able to search for customers, products and orders. The Mutation type defines which data manipulation operations will be available to the consumer. In the example presented, the consumer will be able to create, change and remove customers and products. However, when it comes to orders, he can create, add an item, cancel and close the order. 

In addition to the Query and Mutation types, you can see the presence of the Customer and Product types. In both, there are ID, String and Float properties. These three types, together with Int and Boolean types, are called scalar types. The schema also shows the definition of an enumerate called OrderStatus. Figure 3 shows the definition of Input types that are used to provide input data for queries and mutations. 

I think it's important to point out that the way to create the schema varies depending on the library you choose. When using the Apollo library for javascript, the schema definition can be done through a string passed as a parameter to the gql function or through the creation of a file (generally called schema.graphql). However, when using libraries such as Hot Chocolate for dotNet, the schema definition is done by creating classes and configuring services in the application. Therefore, the way in which a GraphQL schema is created can vary greatly depending on the language and library chosen.  

Figure 2.
Figure 3.

Basic elements of the GraphQL language

As mentioned earlier, GraphQL is a language and therefore has a syntax. You can find the complete guide with the language syntax on the official website of GraphQL. However, in this article, I will describe the basic elements of it.  

Data is searched through queries, which must start with the keyword Query followed by the name of the query. If it has parameters, it must be open parentheses and, within them, you must place the name of each parameter followed by its value. You two points (:) must be used to separate the parameter name from its value. Having finalized the list of parameters, you must close the parentheses. Then, you must open keys ({) and put the name of the fields you want inside them. With the list of fields finalized, you must close the key  (}). Table 3 shows a simple example of a query. 

Table 3: Example of query.

There are scenarios where the query parameters can be complex. When a parameter is complex, that is, it is an object with one or more fields, braces must be opened immediately after the colon. Within the keys, you must place the value of each field of the object and its respective value, both of which must be separated by a colon (see table 4). 

There are also scenarios where the query fields can be complex. In these cases, you must open curly braces right after the field name. Inside the keys, you must place the names of the object field (see table 5). 

Table 4: Example of query.
Table 5: Example of query.

The rules described so far also apply to mutations. However, these must begin with the keyword immigration instead of query. It is interesting to note that there are other elements in the GraphQL syntax, but the elements described so far are sufficient to execute most queries and mutations. 

Being a language, GraphQL needs to be implemented by some application or library. For our API to support queries and mutations, we generally need a library. Of course, we could implement the language specification on our own, but that would be very unproductive. The “Code” section of the website GraphQL.org shows a list of libraries that implement GraphQL for the most varied languages. For the dotNet world, for example, there are the libraries “GraphQL for .NET”, “Hot Chocolate” and others. 

When talking about GraphQL implementations, it is necessary to talk about the concept of “resolvers”. A resolver is a function that is triggered by the library that implements GraphQL. This function is responsible for effectively fetching the data requested by the query. The same occurs with mutations, that is, when the library receives a request to execute a mutation, the library identifies the resolver that will execute the changes in the database (insert, update and delete). Note, then, that in most libraries, searches and changes to data are carried out by their own code. It can be seen, then, that the libraries that implement GraphQL are responsible for interpreting the query/mutation sent by the caller and discovering the appropriate function to resolve the requested query/mutation. To see an example of a simple API that uses Hot Chocolate, visit my GitHub

To sum it all up, GraphQL is a language created by Facebook with the aim of overcoming the problems inherent to REST. The language provides a simple syntax for obtaining data from an API as well as changing data from it. It is implemented by a wide variety of libraries for the most diverse languages, allowing the developer to create a GraphQL API using their favorite language.

References

“GraphQL.” Wikipedia, 9 June 2022, en.wikipedia.org/wiki/GraphQL. Accessed on 6 Nov. 2023. 

The GraphQL Foundation. “GraphQL: A Query Language for APIs.” Graphql.org, 2012, graphql.org/. 

Thomas Fielding, Roy. “Fielding Dissertation: CHAPTER 5: Representational State Transfer (REST).” ics.uci.edu, 2000, ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm. Accessed on 6 Nov. 2023. 

Leave a comment

Your email address will not be published. Required fields are marked with *