Friday, October 29, 2010

Advantage Web API with Windows Phone 7

AdsWeb_WP7_Example Earlier in the week I discussed using the Advantage Web API with Windows Mobile 6 (WM6) in this post I will be discussing using the API with Windows Phone 7 (WP7). The techniques are very similar for both platforms. However, there are several differences with Microsoft's latest mobile platform.

Most notably WP7 applications are written in Silverlight or XNA which are both much different than the Windows Forms model used by WM6. The Silverlight libraries do not include any functions for creating a custom certificate handler, therefore you must use a valid certificate or register your self-signed certificate on the phone. I haven't found a good way of doing this yet so for now I am doing all my testing without SSL. However, you should always use SSL in a production environment.

The mechanism for retrieving data from the Advantage Web API is quite similar to the mechanism used with WM6. For WP7 I will once again use a JSON serializer and a custom class/object to work with the data on the device. Creating the class for the deserializer to work with is very similar to the one I discussed last week. The classes will use the System.Runtime.Serialization library I used an article by Nick Harris as my starting point. The class for the customer summary is below.

[DataContract]
public partial class CustomerSummary : BaseMyContent
{
  [DataMember]
  public string CustomerID { get; set; }
  [DataMember]
  public string CustomerName { get; set; }
  [DataMember]
  public string CustomerCompany { get; set; }
}

Web requests from WP7 are done in an asyncronous manner making the code a bit more complex than making a request with WM6. Additionally Microsoft provides a JSON serializer which is found in the System.Runtime.Serialization.Json library, which can be used to populate the data classes. I'll be using this serializer instead of the JSON.NET libraries.

private void GetData(string URL)
{
  var request = WebRequest.Create(HttpUtility.HtmlEncode(URL)) as HttpWebRequest;
  request.Accept = "application/json";
  request.Headers["Authorization"] = "Basic " + 
          Convert.ToBase64String(Encoding.UTF8.GetBytes(settings.Credentials));
  request.BeginGetResponse(RequestCallback, request);
}

void RequestCallback(IAsyncResult response)
{
  var request = response.AsyncState as HttpWebRequest;
  resp = request.EndGetResponse(response);
            
  if (resp != null)
  {
    var jsonSerializer = new DataContractJsonSerializer(typeof(BaseJSONResult));

    using (var stream = resp.GetResponseStream())
    {
      customerList = jsonSerializer.ReadObject(stream) as BaseJSONResult;
    }

    if (invoiceList.Result != null)
    {
      nextInvoices = invoiceList.Result.NextLinkUri;
      this.Dispatcher.BeginInvoke(() => DataRetrieved());
    }
    else
    this.Dispatcher.BeginInvoke(() => HandleError(invoiceList.Error.ErrorMessage.Value));
  }
}

void DataRetrieved()
{
  PageTitle.Text = "Invoice List";
  listboxCustomers.ItemsSource = customerList.Result.MyContents;
}

void HandleError(string errMessage)
{
  MessageBox.Show(errMessage);
  NavigationService.GoBack();
}

Since the request is processed asyncronously we need to use an Invoker to interact with the UI, hence the this.Dispatcher.BeginInvoke calls. Now that we have the results stored in our class we can now display the data. This is done by setting the ItemsSource property of the listbox and then binding the fields to the controls within the listbox. The xaml for the listboxCustomers is below.

<grid grid.rowspan="2" margin="12,149,12,12" x:name="ContentPanel">
  <listbox margin="0,0,-12,0" x:name="MainListBox" height="607"               selectionchanged="MainListBox_SelectionChanged" itemssource="{Binding Items}">
  <listbox.itemtemplate>
    <datatemplate>
        <stackpanel margin="0,0,0,17" width="432">
          <textblock textwrapping="Wrap" text="{Binding CustomerName}" />
          <textblock margin="12,-6,12,0" textwrapping="Wrap" 
                        text="{Binding CustomerCompany}" />
        </stackpanel>
      </datatemplate>
    </listbox.itemtemplate>
  </listbox>
</grid>

1 comment:

franck said...

HI,

your code is very interesting, but i'm just a beginner in c# developpement for Wp7. Could you send me your source code ?

Thx

Franck