Skip to content

Instantly share code, notes, and snippets.

@benmccallum
Last active February 5, 2020 14:25
Show Gist options
  • Save benmccallum/df9dbf60a205c5be5a1b116cd98d725b to your computer and use it in GitHub Desktop.
Save benmccallum/df9dbf60a205c5be5a1b116cd98d725b to your computer and use it in GitHub Desktop.
Strongly-typed GraphQL Client solution

This gist demonstrates a solution to generating a strongly-typed client for a GraphQL service.

  1. Create a .csproj project (e.g. MyCompany.GraphQL.Queries)
  2. Add some queries using .graphql files
  3. Add the .ps1 script above
  4. Install quicktype
  5. Add a reference to Newtonsoft.Json to the project (required by the generated query files, though that may change in the future to System.Text.Json)
  6. Add a client wrapper that can utilise the query types and deserialize into them (see TypedGraphQLClient.cs)
  7. Use it elsewhere.
Write-Host "Downloading the latest schema from localhost... " -NoNewline
quicktype --http-method "POST" --graphql-introspect http://localhost:33012/graphql --graphql-schema myCompany.gqlschema
Write-Host "Done."
Write-Host "Finding *.graphql files to generate types for... " -NoNewline
$queries = Get-ChildItem -Path .\ -Filter *.graphql -Recurse -File -Name
$queriesLength = $queries.Length
Write-Host "Done. $queriesLength queries found."
$queries | ForEach-Object {
$queryName = [System.IO.Path]::GetFileNameWithoutExtension($_)
$namespace = 'MyCompany.GraphQL.Queries.' + $queryName
$queryPath = $queryName + '\' + $queryName + '.graphql'
$outPath = $queryPath.replace('.graphql', '.cs')
Write-Host "Generating type for $queryName... " -NoNewline
quicktype --src-lang graphql --lang csharp --array-type list --density dense --number-type decimal --graphql-schema myCompany.gqlschema `
--namespace $namespace $queryPath --out $outPath
Write-Host "Done."
}
Write-Host "Deleting the schema... " -NoNewline
Remove-Item myCompany.gqlschema
Write-Host "Done."
exit
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using MyCompany.GraphQL.Queries;
using MyCompany.GraphQL.Queries.ArticleTileQuery;
using GraphQL.Client;
using GraphQL.Common.Request;
using GraphQL.Common.Response;
using Newtonsoft.Json;
namespace GraphQLService.Client
{
public class TypedGraphQLClient : GraphQLClient, IAutoGuruGraphQLClient
{
public TypedGraphQLClient(HttpClient httpClient)
: base(httpClient)
{
}
public async Task<TResult> ExecuteAsync<TResult>(GraphQLRequest request)
{
var graphResponse = await PostAsync(request);
var responseJson = JsonConvert.SerializeObject(new
{
data = graphResponse.Data,
errors = graphResponse.Errors
});
var methodInfo = typeof(TResult).GetMethod("FromJson");
if (methodInfo != null)
{
return (TResult)methodInfo.Invoke(null, new object[] { responseJson });
}
return default;
}
// You could add specific methods to specific typed queries here if desired as shorthand.
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment