GraphQL has been gaining wide adoption every bit a way of edifice and consuming Web APIs. GraphQL is a specification that defines a blazon arrangement, query language, and schema language for your Web API, and an execution algorithm for how a GraphQL service (or engine) should validate and execute queries against the GraphQL schema. It's upon this specification that the tools and libraries for edifice GraphQL applications are built.

In this article, I'll introduce you lot to some GraphQL concepts with a focus on GraphQL schema, resolver, and the query language. If you lot'd like to follow forth, you demand some basic understanding of C# and ASP.NET Core.

Why Use GraphQL?

GraphQL was developed to make reusing the aforementioned API into a flexible and efficient process. GraphQL works for API clients with varying requirements without the server needing to modify implementation equally new clients become added or without the client needing to alter how they use the API when new things become added. It solves many of the inefficiencies that you may experience when working with a REST API.

Some of the reasons you should use GraphQL when edifice APIs are:

  • GraphQL APIs accept a strongly typed schema
  • No more over- or under-fetching
  • Analytics on API utilize and affected data

Let's take a look.

A Strongly Typed Schema as a Contract Between the Server and Client

The GraphQL schema, which can be written using the GraphQL Schema Definition Language (SDL), clearly defines what operations can be performed by the API and the types available. It'due south this schema that the server'south validation engine uses to validate requests from clients to make up one's mind if they can exist executed.

No More than Over-or Nether-Fetching

GraphQL has a declarative way of requesting data using the GraphQL query language syntax. This mode, the client tin can asking whatsoever shape of data they want, as long equally those types and its fields are divers in the schema. This is analogous to REST APIs where the endpoints render predefined and fixed information structures.

This declarative way of requesting data solves ii commonly encountered problems in RESTful APIs:

Over-fetching and Under-fetching

Over-fetching happens when a client calls an endpoint to request information, and the API returns the data the customer needs as well every bit extra fields that are irrelevant to the client. An instance to consider is an endpoint /users/id which returns a user's data. Information technology returns basic information, such as (in this example, an online school's database will be used) name and section, as well equally actress information, such as address, billing information, or other pertinent information, such as courses they're enrolled in, purchasing history, etc. For some clients or specific pages, this actress data can exist irrelevant. A client may simply need the proper name and some identifying information, similar social security number or the courses they're enrolled in, making the extra data such as accost and billing information irrelevant. This is where over-fetching happens, affecting performance. It can too consume more of users' Internet data plan.

Under-fetching happens when an API call doesn't return plenty data, forcing the customer to brand boosted calls to the server to recollect the information it needs. If the API endpoint /users/id only returns data that includes the user'southward proper name and one other fleck of identifying data, clients needing all of the user's information (billing details, address, courses completed, purchasing history, etc.) will accept to request each piece of that information with separate API calls. This affects performance for these types of clients, specially if they're on a slow connection.

This problem isn't encountered in GraphQL applications because the client can request exactly the bits of data they demand from the server. If the client requirement changes, the server need not modify its implementation but rather the client is updated to reverberate the new data requirement past adding the extra field(s) it needs when querying the server. Y'all will learn more about this and the declarative query linguistic communication in GraphQL in the upcoming sections.

Analytics on clients' usage

GraphQL uses resolver functions (which I'll talk about later) to decide the data that the fields and types in the schema returns. Because clients can choose which fields the server should return with the response, it's possible to runway how those fields are used and evolve the API to deprecate fields that are no longer requested by clients.

Setting Up the Project

Y'all'll be building a basic GraphQL API that returns data from an in-memory collection. Although GraphQL is independent of the transport layer, you want this API to be accessed over HTTP, then you'll create an ASP.NET Core project.

Create a new ASP.NET Core project and install the dependencies shown in Effigy one.

Figure 1: The NuGet packages to install
Figure 1: The NuGet packages to install

The first package you installed is the GraphQL package for .Internet. Information technology provides classes that allow you to define a GraphQL schema and also a GraphQL engine to execute GraphQL queries. The 2d package provides an ASP.NET Core middleware that exposes the GraphQL API over HTTP. The third packet is referred to as the GraphQL Playground, which works in a similar mode to Postman for Residuum APIs. Information technology gives you an editor in the browser where you can write GraphQL queries confronting your server and see how it responds. It gives yous IntelliSense and you tin view the GraphQL schema from it.

The GraphQL Schema

The GraphQL schema is at the middle of every GraphQL server. It defines the server's API, assuasive clients to know which operations tin be performed by the server. The schema is written using the GraphQL schema language (too chosen schema definition language, SDL). With information technology, you can define object types and fields to represent data that can be retrieved from the API besides as root types that define the group of operations that the API allows. The root types are the Query type, Mutation type, and Subscription type, which are the iii types of operations that you can run on a GraphQL server. The query type is compulsory for any GraphQL schema, and the other two are optional. Although y'all tin can define custom types in the schema, the GraphQL specification besides defines a set of born scalar types. They are Int, Float, Boolean, String, and ID.

There are two ways of building GraphQL server applications. In that location'south the schema-first approach where the GraphQL schema is designed upward front end. The other approach is the code-first approach where the GraphQL is constructed programmatically. The code-first approach is common when edifice a GraphQL server using a typed language like C#. You're going to use the code-get-go approach here and later on look at the generated schema.

Permit's get started with the schema. Create a new folder chosen GraphQL and add a new file Book.cs with the content in the following snippet:

          public class Book{     public int Id { get; set; }     public string Title { get; fix; }     public int? Pages { get; set; }     public int? Chapters { go; ready; }}                  

Add some other class BookType.cs and paste the content from the next snippet into it.

          using GraphQL.Types; public class BookType : ObjectGraphType<Book> {     public BookType()     {         Field(x => 10.Id);         Field(10 => x.Title);         Field(ten => x.Pages, nullable: true);         Field(x => x.Capacity, nullable: true);     } }                  

The code in the concluding snippet represents a GraphQL object type in the schema. It'll have fields that volition match the properties in the Book class. Y'all set the Pages and Chapters fields to be nullable in the schema. If not set, by default, the GraphQL .Net library sets them as non-nullable.

The application you're building simply allows querying for all the books and querying for a book based on its ID. The book type is defined so go alee and define the root query blazon. Add a new file RootQuery.cs in the GraphQL folder, then copy and paste the code from Listing one into it.

Listing 1: The type for the root query operation

          using GraphQL.Types; using System.Collections.Generic; using Organization.Linq;  public class RootQuery : ObjectGraphType {     public RootQuery()         {             Field<ListGraphType<BookType >>("books", resolve:                 context => GetBooks());             Field<BookType>("book", arguments : new QueryArguments(             new QueryArgument<IdGraphType> { Name = "id" }             ), resolve: context =>             {                  var id = context.GetArgument<int>("id");                  return GetBooks().FirstOrDefault(x => x.Id == id);              });         }      static List<Book>GetBooks()     {         var books = new List <Book>{             new Book {                 Id = ane,                 Title = "Fullstack tutorial for GraphQL",                 Pages = 356             },             new Book             {             Id = 2,             Championship = "Introductory tutorial to GraphQL",             Chapters = 10             },             new Book            {            Id = 3,            Title = "GraphQL Schema Pattern for the Enterprise",            Pages = 550,            Capacity = 25            }        };         return books;     } }                  

The RootQuery form will be used to generate the root operation query type in the schema. It has two fields, book and books. The books field returns a list of Volume objects, and the volume field returns a Book blazon based on the ID passed equally an argument to the volume query. The type for this argument is divers using the IdGraphType, which translates to the built in ID scalar type in GraphQL. Every field in a GraphQL type tin can have zero or more arguments.

You'll also detect that you're passing in a function to the Resolve parameter when declaring the fields. This function is chosen a Resolver function, and every field in GraphQL has a corresponding Resolver function used to determine the data for that field. Remember that I mentioned that GraphQL has an execution algorithm? The implementation of this execution algorithm is what transforms the query from the client into actual results by moving through every field in the schema and executing their Resolver function to make up one's mind its effect.

The books resolver calls the GetBooks() static function to return a list of Book objects. You'll discover that information technology's returning a list of Book objects and not BookType, which is the type tied to the schema. GraphQL for .Internet library takes care of this conversion for you.

The Book resolver calls context.GetArgument with id equally the proper name of the statement to retrieve. This statement is and then used to filter the list of books and return a matching record.

The last footstep needed to end the schema is to create a class that represents the schema and defines the operation allowed by the API. Add a new file GraphSchema.cs with the content in the following snippet:

          using GraphQL; using GraphQL.Types;  public grade GraphSchema : Schema {     public GraphSchema(IDependencyResolver resolver) : base(resolver)     {         Query = resolver.Resolve<RootQuery>();     } }                  

In that bit of code, you created the schema that has the Query property mapped to the RootQuery divers in Listing 1. Information technology uses dependency injection to resolve this blazon. The IDependencyResolver is an brainchild over whichever dependency injection container yous use, which, in this example, is the i provided by ASP.NET.

Configuring the GraphQL Middleware

At present that you have the GraphQL schema defined, yous demand to configure the GraphQL middleware and then it tin respond to GraphQL queries. Y'all'll practise this inside the Startup.cs file. Open that file and add the following using statements:

          using GraphQL; using GraphQL.Server; using GraphQL.Server.Ui.Playground;                  

Go to the ConfigureServices method and add the code snippet you encounter below to it.

          services.AddScoped<IDependencyResolver>     (s => new FuncDependencyResolver (southward.GetRequiredService));  services.AddScoped<GraphSchema>(); services.AddGraphQL().AddGraphTypes(ServiceLifetime.Scoped);                  

The code in that snippet configures the dependency injection container so that when something requests a particular type of FuncDependencyResolver from IDependencyResolver that it should return. In the lambda, you call GetRequiredServices to hook it upwardly with the internal dependency injection in ASP.NET. Then you added the GraphQL schema to the dependency injection container and used the code services.AddGraphQL extension method to annals all of the types that GraphQL.net uses, and likewise call AddGraphTypes to browse the assembly and register all graph types such as the RootQuery and BookType types.

Let's move on to the Configure method to add lawmaking that sets upward the GraphQL server and also the GraphQL playground that is used to test the GraphQL API. Add together the code snippet below to the Configure method in Startup.cs .

          app.UseGraphQL<GraphSchema>(); app.UseGraphQLPlayground(new GraphQLPlaygroundOptions());                  

The GraphQL Query Linguistic communication

So far, you've defined the GraphQL schema and resolvers and have too set up upwardly the GraphQL middleware for ASP.NET, which runs the GraphQL server. You at present demand to first the server and exam the API.

Start your ASP.NET application past pressing F5 or running the command dotnet run*. This opens your browser with the URL pointing to your awarding. Edit the URL and add /ui/playground at the end of the URL in order to open the GraphQL playground, as you run into in Effigy 2.

Figure 2:  The GraphQL Playground opened in the browser
Effigy 2: The GraphQL Playground opened in the browser

The GraphQL playground allows you to test the server operations. If yous've congenital Balance APIs, recall of information technology as a Postman culling for GraphQL.

Now permit'southward ask the server to list all the books it has. You lot do this using the GraphQL query language, another concept of GraphQL that makes information technology piece of cake for different devices to query for data how they want, served from the same GraphQL API.

Go to the GraphQL playground. Re-create and run the query y'all come across on the left side of the editor in Figure three, then click the play button to transport the query. The result should friction match what you see on the correct-hand side of the playground, as shown in Figure 3.

Figure 3: The query results on books
Figure 3: The query results on books

Y'all'll notice that the query is structured similarly to the schema language. The books field is one of the root fields defined in the query blazon. Inside the curly braces, y'all have the pick assault the books field. Because this field returns a list of Book type, you specify the fields of the Book type that you want to call up. You omitted the pages field; therefore it isn't returned by the query.

Yous tin can test the book(id) query to retrieve a book by its ID. Await at Figure 4 and run the query yous run across there to retrieve a book. In that query, you fix the id argument to a value of 3, and it returned exactly what you lot need. You'll discover that I have two queries, books and book(id: iii). This is a valid query. The GraphQL engine knows how to handle it.

Figure 4: The query results on books and book(id: 3)
Figure 4: The query results on books and volume(id: three)

What'south Next?

So far, I've covered some basics of GraphQL. You looked at defining a schema using the code-outset approach, writing resolver functions, and querying the GraphQL API. You created a server using the GraphQL package for .Net, the NuGet bundle GraphQL.Server.Transports.AspNetCore, which is the ASP.Internet Core middleware for the GraphQL API, and GraphQL.Server.Ui.Playground parcel that contains the GraphQL playground. You used the GraphQL playground to test your API. I explained that in GraphQL, in that location are three functioning types. In this commodity, you worked with the query operation; in the next article, yous'll await at mutations and accessing a database to shop and remember data. You lot'll update your schema so yous can query for related data, due east.thousand., authors with their books, or books from a particular publisher. Stay tuned!!