mardi 14 mars 2017

Using GraphQL in your Windows Application part II - using mutations [UWP,NET,GraphQL]

In this article we are going to see how we can do a Mutation in GraphQL in your .NET app, you will be able to find more documentation about mutations here: http://graphql.org/learn/queries/

We will be using the same endpoints and example as in the previous article:
Using GraphQL in your Windows Application part I [UWP,NET,GraphQL]

Just like the previous article related to querying GraphQL, you will need a text file that will hold a JSON mutation query as follow:

mutation($input: FavBookInput!){
  favoriteBook(input:$input){
    status
    clientMutationId
  }
}

Next we will need to create a Class what will hold the variables that we will pass in our query:

namespace GraphQL.QlFiles.M
{
    public class QueryAddToFavBooksMutationModel
        {
        public BookInput input { get; set; }
    }
    public class BookInput
    {
        public string bookXid { get; set; }
    }
}

Here are the string const that we will be using:

 public const string GrapgQL_PARAM_Query_and_Variables_To_CALL = "query={0}&variables={1}";
 public const string GRAPHQL_URL_BASE = "https://graphql.api.abcde.com/";
 public const string MyMutationQueryCallFile = "ms-appx:///QlFiles/M/AddToFavBooks.txt";

Doing a mutation on GraphQL is very much like doing a classic GET HTTP GraphQL query but you also need to pass variable in the query.  You will need to intenciante the QueryAddToFavBooksMutationModel class with the correct value so that you can add the correct book to your favorites.  Next you will convert the class to JSON and pass this it to your query as follows:

 private async void GraphQLMutationQuery()
        {
            //prepartion the variables that will be sent for the get query
            var myMutation = new QueryAddToFavBooksMutationModel()
            {
                input = new BookInput()
                {
                    bookXid = "ABC"
                }
            };

            //getting ou file
            var queryParams = await FileIOReaderHelper.ReadFromDefaultFileAsync(MyMutationQueryCallFile);

            //serializing our class to json so that we can send it in the GET call.
            string Variables = JsonConvert.Serialize(myMutation);

            var paramsToCall = String.Format(GrapgQL_PARAM_Query_and_Variables_To_CALL,
                            WebUtility.UrlEncode(queryParams),
                            WebUtility.UrlEncode(Variables)
                        );

            //creating our query
            var urlQuery = String.Format("{0}?{1}", GRAPHQL_URL_BASE, paramsToCall);

            //now you can do your http call 
            var response = await HttpClient.SendAsync(urlQuery);
        }





And there you have it you can now do mutations on GraphQL. This could be greatly improved, however for our example this gets the job done.

Happy coding.

jeudi 2 mars 2017

Using GraphQL in your Windows Application part I [UWP,NET,GraphQL]

init()

In this article we are going to see how can query a GraphQL endpoint, in the next article we are going to see how you could do a Mutation.

Here is a quick overview of what GrapgQL is http://graphql.org/ 

FYI: GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data. GraphQL isn't tied to any specific database or storage engine and is instead backed by your existing code and data.

Now lets say that we have this end point https://grapql.api.MyWebsite.com

Also lets say that on this endpoint I can query it as follow:


fragment BookFields on Book {
  xid
  title
  author
  thumbnails
  year
}

{
  views {
    sections {
      edges {
        node {
          name
          title
          components {
            edges {
              node {
                __typename
                ...BookFields
              }
            }
          }
        }
      }
    }
  }
}


And lets say that the endpoint will respond with the following json payload:

{
  "data": {
    "views": {
       "sections": {
          "edges": [
            {
              "node": {
                "name": "HarryPotter_books",
                "title": "Harry Potter Books",
                "components": {
                  "edges": [
                    {
                      "node": {
                        "__typename": "Books",
                        "xid": "A1",
                        "author": "J. K. Rowling",
                        "title": "Harry Potter : The Philosopher's Stone",
                        "thumbnails": "https://ABC.net/x240-nEZ.jpg",                        
                        "year": 1997
                        }
                     
                    },
                    {
                      "node": {
                        "__typename": "Books",
                        "xid": "A1",
                        "author": "J. K. Rowling",
                        "title": "Harry Potter : The Chamber of Secrets",
                        "thumbnails": "https://ABC.net/x240-nEZ.jpg",                        
                        "year": 1998
                        }
                    },
     {
                      "node": {
                        "__typename": "Books",
                        "xid": "A1",
                        "author": "J. K. Rowling",
                        "title": "Harry Potter : The Prisoner of Azkaban",
                        "thumbnails": "https://ABC.net/x240-nEZ.jpg",                        
                        "year": 1999
                        }
                    },
     {
                      "node": {
                        "__typename": "Books",
                        "xid": "A1",
                        "author": "J. K. Rowling",
                        "title": "Harry Potter : The Goblet of Fire",
                        "thumbnails": "https://ABC.net/x240-nEZ.jpg",                        
                        "year": 2000
                       }
                    }
                  ]
                }
              }
            }
          ]
        }
      }
    }
  }
}

Now we convert this JSON to C# classes:


public class NodeItem
{
    public string __typename { get; set; }
    public string xid { get; set; }
    public string author { get; set; }
    public string title { get; set; }
    public string thumbnails { get; set; }
    public int year { get; set; }
}

public class EdgeItem
{
    public NodeItem node { get; set; }
}

public class Components
{
    public List<EdgeItem> edges { get; set; }
}

public class Node
{
    public string name { get; set; }
    public string title { get; set; }
    public Components components { get; set; }
}

public class Edge
{
    public Node node { get; set; }
}

public class Sections
{
    public List<Edge> edges { get; set; }
}

public class Views
{
    public Sections sections { get; set; }
}

public class Data
{
    public Views views { get; set; }
}

public class RootObject
{
    public Data data { get; set; }
}


Ok now that we can create a blank UWP app, add 2 folders one for the models and one for the GraqhQL txt file.  In my solution the folders are called Model and QlFiles.  In QlFiles we will add a txt file called MyQuery.txt that will hold our query.

Next we will need to read this json text file using :

await StorageFile.GetFileFromApplicationUriAsync(appUri);
and 
await FileIO.ReadTextAsync(anjFile);

And now we just need to format our get query and we can do the HTTP call.


public sealed partial class MainPage : Page
{
        public const string GrapgQL_PARAM_To_CALL = "query={0}";
        public const string GRAPHQL_URL_BASE = "https://graphql.api.abcde.com/";
        public const string MyQueryCallFile = "ms-appx:///QlFiles/MyQuery.txt";

        public MainPage()
        {
            this.InitializeComponent();
            Loaded += MainPage_Loaded;
        }

        private async void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            //Fetching the json from the txt file
var queryParams = await FileIOReaderHelper.ReadFromDefaultFileAsync(MyQueryCallFile);
            
            //merging the parms for the query
var paramsToCall = String.Format(GrapgQL_PARAM_To_CALL,
                                             WebUtility.UrlEncode(queryParams));
            //Creating the query to call
var urlQuery = String.Format("{0}?{1}",
                                         GRAPHQL_URL_BASE,        
                                         paramsToCall);

            //doing the http call 
            var response = await HttpClient.SendAsync(urlQuery);
            var responseJson = await response.Content.ReadAsStringAsync();

            //you can deserialize with the RootObject class you created
            var responseObject = JsonService.DeserializeObject<RootObject>(responseJson);

        }

        public static class FileIOReaderHelper
        {
            //Read the content from Json file 
            public static async Task<string> ReadFromDefaultFileAsync(string fileName)
            {
                if (string.IsNullOrWhiteSpace(fileName))
                {
                    throw new ArgumentNullException(nameof(fileName));
                }

                Uri appUri = new Uri(fileName);

                IStorageFile anjFile = await StorageFile.GetFileFromApplicationUriAsync(appUri);

                string txtFile = await FileIO.ReadTextAsync(anjFile);

                return txtFile;

            }
        }
}


As of today as you can see using GraphQL in you .NET application is a bit hash and not developer friendly.  If by any chance you have a cleaner way of doing it don't hesitate to comment!

Happy coding!