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);
        }





NAd 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!



dimanche 1 janvier 2017

Using .NET WebAuthenticationBroker for Google Login in your Windows 10 application [UWP,C#,GOOGLE]

I was fighting with my Google login on my UWP app and thus thought that it would be great if I just copied and pasted my code here so that it might help others.

Long story short, I did not want to use the google SDK to log into my app so I ended up using WebAuthenticationBroker.AuthenticateAsync.   For the WebAuthenticationBroker you need a startUrl and a endUrl which you can find here:
var googleUrl = new System.Text.StringBuilder();
            googleUrl.Append("https://accounts.google.com/o/oauth2/auth?client_id=");
            googleUrl.Append(Uri.EscapeDataString(ClientID));
            googleUrl.Append("&scope=");
            googleUrl.Append(Uri.EscapeDataString("https://www.googleapis.com/auth/plus.profile.emails.read"));
            googleUrl.Append("&redirect_uri=");
            googleUrl.Append(Uri.EscapeDataString("urn:ietf:wg:oauth:2.0:oob"));
            googleUrl.Append("&response_type=code");


string endURL = "https://accounts.google.com/o/oauth2/approval?";


One small problem, was that when using WebAuthenticationBroker on UWP you don't get an access token but a authorization code which doesn't really help you,  because you cant authenticate with an authorization code, I needed an access token.

What we need to do next is a POST call on  https://accounts.google.com/o/oauth2/token
with my client id, client secret and authorization code and a few other parameters, here is the full list:
 var pairs = new Dictionary<string, string>();
                    pairs.Add("code", authorizationCode);
                    pairs.Add("client_id", ClientID);
                    pairs.Add("client_secret", ClientSecret);
                    pairs.Add("grant_type", "authorization_code");
                    pairs.Add("redirect_uri", "urn:ietf:wg:oauth:2.0:oob");

We encode the content:
var formContent = new HttpFormUrlEncodedContent(pairs);

Next we do our POST call:
await client.PostAsync(new Uri("https://accounts.google.com/o/oauth2/token"), formContent);

And Voila you have your auth token =)
string response = await httpResponseMessage.Content.ReadAsStringAsync();

Full code here:
Warning to people that like sexy code this will hurt you eyes:

 public async Task<string> LogIntoGoogleClean()
 {
            var googleUrl = new System.Text.StringBuilder();
            googleUrl.Append("https://accounts.google.com/o/oauth2/auth?client_id=");
            googleUrl.Append(Uri.EscapeDataString(ClientID));
            googleUrl.Append("&scope=");
            googleUrl.Append(Uri.EscapeDataString("https://www.googleapis.com/auth/plus.profile.emails.read"));
            googleUrl.Append("&redirect_uri=");
            googleUrl.Append(Uri.EscapeDataString("urn:ietf:wg:oauth:2.0:oob"));
            googleUrl.Append("&response_type=code");

            //approval
            string endURL = "https://accounts.google.com/o/oauth2/approval?";

            Uri startUri = new Uri(googleUrl.ToString());
            Uri endUri = new Uri(endURL);

            try
            {
                // Using WebAuthenticationBroker
                WebAuthenticationResult webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.UseTitle, startUri, endUri);

                //Checking to see if we haev succeded
                if (webAuthenticationResult.ResponseStatus == WebAuthenticationStatus.Success)
                {
                    Debug.WriteLine("ResponseData: " + webAuthenticationResult.ResponseData);

                    //getting just the autorizationCode to continue and get the token 
                    var authorizationCode = webAuthenticationResult.ResponseData.Substring(13);

                    //lets get crazy and get the access token so that i can really login
                    var pairs = new Dictionary<string, string>();
                    pairs.Add("code", authorizationCode);
                    pairs.Add("client_id", ClientID);
                    pairs.Add("client_secret", ClientSecret);
                    pairs.Add("grant_type", "authorization_code");
                    pairs.Add("redirect_uri", "urn:ietf:wg:oauth:2.0:oob");


                    var formContent = new HttpFormUrlEncodedContent(pairs);

                    //please dont hate me but this is dirty
                    var client = new HttpClient();
                    var httpResponseMessage =
                        await client.PostAsync(new Uri("https://accounts.google.com/o/oauth2/token"), formContent);
                    string response = await httpResponseMessage.Content.ReadAsStringAsync();

                    //but at least I got it to work :P
                    GoogleAccessToken token = JsonConvert.DeserializeObject<GoogleAccessToken>(response);

                    //return access token
                    return token.access_token;
                }
                else
                    return webAuthenticationResult.ResponseStatus.ToString();
            }
            catch (Exception Error)
            {
                //report the issue
App.RepportError(Error); } return "error"; }

Happy Coding!