Blog

All Blog Posts

WP7 Insights #1: Consuming REST APIs within a WP7 app

This article is the first in a series which discusses some of the things that I learned while developing my first Windows Phone 7 application. My first Windows Phone 7 application, Dwolla, was accepted into the marketplace about a month ago.  Our friends at Dwolla (www.dwolla.com) already had an app for the iPhone and Android platforms, but did not have any plans to pursue the WP7 platform in the near future.  I took this as an opportunity to learn about Windows Phone development and provide a tool for Dwolla consumers. Dwolla has REST APIs available for Developers.  After reviewing these APIs I had a couple of challenges in consuming these for Silverlight applications and WP7 apps.
  • Each API is a POST.  I had consumed APIs in Silverlight using GET, but not POST.
  • The results were returned in JSON format.  My background was consuming SOAP Web Services so JSON was a bit new to me.
Consuming the APIs in Silverlight After some research I came up with the following approach to consuming the Dwolla APIs.  Here is an example for the "account_information" method. I'll be working with parameters so I have the following. public string BuildParameters(Dictionary<string, string> parameters) { List<string> list = new List<string>(); foreach (string key in parameters.Keys) { list.Add(string.Format(""{0}" : "{1}"", key, parameters[key])); } return "{" + string.Join(",", list.ToArray()) + "}"; }   public class MyState { public HttpWebRequest Request { get; set; } public Dictionary<string, string> Parameters { get; set; } }   The following code sets up the API call.  A couple of things to note about this method.
  • Adding parameters was easy using the Dictionary and storing that in MyState class.
  • I had to set both the ContentType and Accept values for the HttpWebRequest object to "application/json" to get my method to work correctly.  I initially had ContentType but later found that I also needed Accept.
  private void GetAccountInformation(string email, string password) { try { DwollaLibrary dwollaLibrary = new DwollaLibrary();   string url = dwollaLibrary.GetDwollaJsonURL() + "/account_information";   Dictionary<string, string> parameters = new Dictionary<string, string>(); parameters.Add("APIUsername", dwollaLibrary.GetAPIKey()); parameters.Add("APIPassword", dwollaLibrary.GetAPICode()); parameters.Add("AccountIdentifier", email); parameters.Add("Password", password);   HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); request.Method = "POST"; request.ContentType = "application/json"; request.Accept = "application/json";   MyState state = new MyState(); state.Request = request; state.Parameters = parameters; request.BeginGetRequestStream(LoadRequestBegin, state); } catch (Exception) { myProgress.Visibility = Visibility.Collapsed; } }   Setup the parameters and call to get the response. private void LoadRequestBegin(IAsyncResult result) { try { var dwollaLibrary = new DwollaLibrary(); var state = (MyState)result.AsyncState; HttpWebRequest request = state.Request; using (Stream stream = request.EndGetRequestStream(result)) { using (StreamWriter writer = new StreamWriter(stream)) { string jsonParams = BuildParameters(state.Parameters); writer.Write(jsonParams); } } request.BeginGetResponse(LoadRequestComplete, request);   } catch (Exception) { myProgress.Visibility = Visibility.Collapsed; } }   Here is the method to handle the response.  Some notes:
  • I get the JSON results back in the response and get that string setup to load into my AccountInformation class.
  • I am using the DataContractJsonSerializer class to load the JSON string into my AccountInformation class.  Note the line where I declare "accountInformation".  The constructor of the AccountInformation class handles this.  This code is in the next section.
  private void LoadRequestComplete(IAsyncResult result) { try { string json = ""; this.Dispatcher.BeginInvoke(delegate() { try { HttpWebRequest request = (HttpWebRequest)result.AsyncState; WebResponse response = request.EndGetResponse(result); using (Stream stream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(stream)) { json = reader.ReadToEnd(); } }   string jsonResults = json.Replace("{"AccountInformationResult":", "").Replace("}}", "}"); var accountInformation = new AccountInformation(jsonResults); if (accountInformation.Id != "") { txtAccount.Text = accountInformation.Id; txtBalance.Text = string.Format("{0:C}", accountInformation.Balance); } myProgress.Visibility = Visibility.Collapsed; } catch (Exception) { myProgress.Visibility = Visibility.Collapsed; } }); } catch (Exception ex) { myProgress.Visibility = Visibility.Collapsed; } }   Parsing out the data.  I found that the DataContractJsonSerializer class is pretty cool - parses the JSON string into my class automagically.  The following code snippets accomplishes this.   using System.Runtime.Serialization.Json; using System.IO; using System.Text;   namespace DwollaApp.Components { public static class Extensions { public static T FromJSON<T>(this T obj, string json) where T : class { using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(json))) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T)); return serializer.ReadObject(stream) as T; } } }   public class AccountInformation { public AccountInformation() { }   public AccountInformation(string json) { AccountInformation accountInfo = this.FromJSON(json);   _id = accountInfo.Id; _name = accountInfo.Name; } ... } } Once I had this framework in place I was able to use this approach for all of my API calls.  If you have a WP7 phone you can download the Dwolla app and give it a try.  You will need to setup a free account at www.dwolla.com to establish your account. Happy coding!