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!