Querying data with GraphQL

You can use GraphQL to access data from your back-end service and apply a query on it in order to return the needed information only.
It is an open source specification, invented by Facebook, which serves as a middle man, a communication between the client and the back-end.
Its syntax is similar to JSON:

{
  person(id: 123) {
    name
    age
  } 
}

And that query will produce a JSON like this as a response:

{
  "person": {
    "name": "John Smith"
    "age": "33"
  }
}

So imagine you have an API or web site and you want to consume a specific data. You can get only the fields you want by applying a GraphQL query describing only the required ones. We are going to see an example using a GraphQL over ASP.NET Core application.

There are several main components you have to know for building a GraphQL API.

  • Schema – thant is the core thing and describes all the functionalities available for a client.
  • Query is the client request to retrieve data from the server (DB, API)
  • Mutation is a query which purpose is to modify (update, delete or add) some data in the DB (the data store)
  • Type – this is a graph type which will describe the object’s metadata. The fields for the concrete type should be created in the constructor. GraphQL have built in graph types and will do the mapping between our entity properties and the GraphQL ones. You can check the types mapping (for .NET) here.
  • Client – GraphQL can be consumed by every platform which can do HTTP requests and for that we need a client for the API. It can be a System.Net.Http.HttpClient to be used in a .NET application, or a GraphQLClient for .NET (from GraphQL.Client namespace), or a client like Apollo.

Example

Now let’s try it with a real .NET Core Web API application.

Just a note that this is not a .NET Core educational post, so I will skip the details about creating and setup a project.

Initially we are going to create our sample model called ValueModel (this name is used only for the purposes of this demo. Otherwise always use a good, descriptive names for your classes!)

 public class ValueModel
 {
        public ValueModel(int id, string name, string description, int quantity)
        {
            Id = id;
            Name = name;
            Description = description;
            Quantity = quantity;
        }       

        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public int Quantity { get; set; }
  }

Now let’s create our service which will return a collection of ValueModel objects. (Remember this is a GraphQL demonstration, so I am going to simply return a predefined list of hard-coded values, instead of fetching them from a DB through a repository layer, which you will have to do in a real application).

public interface IValuesService
{
    IEnumerable<ValueModel> GetAllValues();
}
public class ValuesService : IValuesService
    {
        public IEnumerable<ValueModel> GetAllValues()
        {
            return new List<ValueModel>
            {
                new ValueModel(1, "value1", "description1", 12),
                new ValueModel(2, "value2", "description2", 1),
                new ValueModel(3, "value3", "description3", 10),
                new ValueModel(4, "value4", "description4", 8),
                new ValueModel(5, "value5", "description5", 5),
            };
        }
    }

In order to inject the ValueService dependency we need to register it in the Startup.cs under the ConfigureServices method:

services.AddScoped<IValuesService, ValuesService>();

Now we can go ahead with the GraphQL objects, but firs of all we need to install several NuGet packages. Start with the GraphQl package through the Package Manager Console:

PM> Install-Package GraphQL -Version 2.4.0

Another nuget package we are going to use is the GraphQL Playground, which is going to be needed in order to run the GraphQL query window through our application and to have the ability to execute direct queries against our data with our models. It is  is a graphical, interactive, in-browser GraphQL IDE, created by Prisma and based on GraphiQL. ( https://www.apollographql.com/docs/apollo-server/features/graphql-playground/ )

PM> Install-Package GraphQL.Server.Ui.Playground -Version 3.4.0

I’ve created a folder named GraphQL to collect all of the GraphQL specific objects there.
So let’s create our Type object in it (also you can create a Types folder in there):

public class ValuesType : ObjectGraphType<ValueModel>
{
    public ValuesType()
    {
        Field(t => t.Id);
        Field(t => t.Name);
        Field(t => t.Description);
        Field(t => t.Quantity);
    }
}

The ValuesType will inherit from ObjectGraphType<TSourceType> which is part of the GraphQL assembly, so a using will be needed here (using GraphQL.Types;)

As for the first example we want to have a select statement which will get all of the Values. That means we need a query object (not a Mutation). So we are going to create the Query class like this (with using GraphQL.Types; again):

public class MyQuery : ObjectGraphType
{
    public MyQuery(IValuesService valuesService)
    {
        Field<ListGraphType<ValuesType>>(
           "values",
           resolve: context => valuesService.GetAllValues()
       );
    }
}

And now go ahead and create the Schema class and the needed usings and registrations:

using GraphQL;
using GraphQL.Types;
public class MySchema : Schema
{
    public MySchema(IDependencyResolver dependencyResolver) : base(dependencyResolver)
    {
        Query = dependencyResolver.Resolve<MyQuery>();
    }
}
public class Startup
{
    ...

    public void ConfigureServices(IServiceCollection services)
    {
        ...
        services.AddScoped<MySchema>();
        ...
    } 

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
         ...
         app.UseGraphQL<MySchema>();
    }
}

Then we need to create our API’s controller. I’m just calling it ValuesController for the sake of the demo. Inside it we are going to add one Get method

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    private readonly ValuesClient client;

    public ValuesController(ValuesClient client)
    {
        this.client = client;
    }

    // GET api/values
    [HttpGet]
    public Task<Response<ValuesContainer>> Get()
    {
        var values = client.GetValues();

        return values;
    }
}

Finally we need to create our HTTP client which will be serving our connection.

public class ValuesClient
{
    private readonly HttpClient httpClient;

    public ValuesClient(HttpClient httpClient)
    {
        this.httpClient = httpClient;
    }

    public async Task<Response<ValuesContainer>> GetValues()
    {
        var response = await httpClient.GetAsync(@"?query= 
        { values 
            { id name quntity description } 
        }");

        var stringResult = await response.Content.ReadAsStringAsync();
        return JsonConvert.DeserializeObject<Response<ValuesContainer>>(stringResult);
    }
}
public class Response<T>
{
    public T Data { get; set; }
}

public class ValuesContainer
{
    public List<ValueModel> Values { get; set; }
}

The client needs to be registered in the container (in Startup class):

services.AddHttpClient<ValuesClient>(o => o.BaseAddress = new Uri("https://localhost:44363/graphql"));

Also we need to register all the types GraphQL uses like this:

services.AddGraphQL(o => { o.ExposeExceptions = false; })
    .AddGraphTypes(ServiceLifetime.Scoped);

Write a query

You can give it a try and play around even with the GraphQL playground UI.
It can be launched with the following URL: https://localhost:port/ui/playground

A query like this one:

{
  values{
    id, description, quantity
  }
}

Will return the following JSON:

{
  "data": {
    "values": [
      {
        "id": 1,
        "description": "description1",
        "quantity": 12
      },
      {
        "id": 2,
        "description": "description2",
        "quantity": 1
      },
      {
        "id": 3,
        "description": "description3",
        "quantity": 10
      },
      {
        "id": 4,
        "description": "description4",
        "quantity": 8
      },
      {
        "id": 5,
        "description": "description5",
        "quantity": 5
      }
    ]
  }
}

You can also execute a Get request to the Values API endpoint and compare the returned result. You can see it is the same as this from the playground.

https://localhost:<port>/api/values

Resources

Below I have listed some resources about the topic:

2 thoughts on “Querying data with GraphQL

Leave a Reply to Alev Ryustemov Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s