Windows Phone 7 Line of Business App Dev :: Consuming an Azure WCF REST + JSON Service

| October 27, 2010 | 5 Comments

In my last two articles, I showed you how to build WCF REST services using Visual Studio 2010 that can reside on-premise in Windows Server 2008 or in the Cloud in Windows Azure.  Furthermore, I demonstrated pulling data from a table in SQL Server/SQL Azure.  I serialized .NET Objects using lightweight JSON to speed data transfers over even the slowest wireless data networks.  Now it’s time to call that REST service from Windows Phone 7.

Launch VS2010 and open the solution you created to build the WCF Service Web Role in Azure last time.  Right-click on the solution and add a Windows Phone Application project.  Change the name to ContosoPhone.

WP71

Part of the magic of making all this work is to have both the Azure Development Fabric and the Windows Phone 7 project start when it comes time to debug.  Most developers are accustomed to only having a single startup project so let’s make sure you have everything we need running when you hit F5.  Right-click on the solution and select Properties.  Select Startup Project and then click on the Multiple startup projects radio button.  Set both the AzureRestService and ContosoPhone projects Action value to Start and click OK as shown below:

WP72

With the startup configuration complete, the next thing I want you to do is copy Customer.cs from the AzureRestService project to the new ContosoPhone project since you’ll need it to create local Customer objects when you retrieve the data from the WCF call.  In this new Customer class you’ll need to change the Namespace to ContosoPhone and remove using System.Web; at the top of the class.  In order to support the DataContract() and DataMember() attributes, you’ll need to add a reference to System.Runtime.Serialization in order to get it to compile.

Drag a Button on to your MainPage.xaml and call it Test.  Double-click on this Button and add the following WebClient code to the click event:

try
{
    WebClient webClient = new WebClient();
    Uri uri = new Uri("
http://127.0.0.1:48632/service1.svc/getdata?number=8");
    webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(OpenReadCompletedTest);
    webClient.OpenReadAsync(uri);
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

As you can see above, I create a WebClient and a Uri object that points to the local Url presented by the Azure Development Fabric.  The port number my be different on your machine so double-check.  This is the test REST service from the last article used to prove that you’re calls are making it through.  You’ve made this call with your web browser and Windows Phone 7 will call it the same way.  Since all calls are asynchronous and the WebClient above created an event handler, copy the following code into the MainPage class and make sure to add using System.IO; at the top:

void OpenReadCompletedTest(object sender, OpenReadCompletedEventArgs e)
{
    try
    {
        StreamReader reader = new System.IO.StreamReader(e.Result);
        MessageBox.Show(reader.ReadToEnd().ToString());
        reader.Close();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

In the event handler above, I use the StreamReader to grab the entire XML return value.  The fact that I’m using WebClient means that callbacks are run on the UI thread thus relieving you of the need to use the dispatcher to update the UI.  This allows you to display the following XML string in the MessageBox:

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">You entered: 8</string>

It’s time to try this thing out so hit F5.  If it compiles and everything executes properly, you should see both a web browser pointing to the root of your Azure services as well as your emulator and you can test your services with both.  Click the simple Test Button on your Silverlight MainPage and the MessageBox should pop up after the XML result is returned from Azure displaying the answer:

WP73

Click the Back button on the Emulator to close your app and close the web browser window to shut down Azure. 

Now it’s time to do something a little more ambitious like return the JSON-encoded list of Customers from SQL Azure.  Unlike most books and articles on Silverlight and RIA Services that you may have read, I’m not going to return this data and immediately data-bind it to a control.  As a long-time mobile and wireless guy that understands intermittent connectivity and the importance of an offline data store, I’m going to have you put this data in a local database first.  Since SQL Server Compact is nowhere to be found and I don’t want you going off and using a 3rd party or open source embedded database, I’m going to show you how to create a simple one of your own.

Right-click on your ContosoPhone project and select Add | Class.  Name this new class Database

WP74

You’re going to turn this class into a Singleton to create an in-memory database which will ensure that only instance is available.  For simplicity’s sake, just copy the code below into the new Database class:

using System;
using System.Net;
using System.Windows;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace ContosoPhone
{
    sealed class Database
    {
        //Declare Instance
        private static readonly Database instance = new Database();

        //Private Constructor
        private Database() { }

        //The entry point into this Database
        public static Database Instance
        {
            get
            {
                return instance;
            }
        }

        //Declare Private Variables
        private ObservableCollection<Customer> customerTable = null;

        //Customer Table
        public ObservableCollection<Customer> Customers
        {
            get { return customerTable; }
            set { customerTable = value; }
        }
    }
}

As you can see above, I’ve had you create a sealed class with a private, static, readonly constructor as an entry point following a popular .NET method of implementing a Singleton.  The big thing here is the Customers property of type ObservableCollection<Customer>.  Since each Customer object is a Row with properties that are Columns, then it’s easy to think of this ObservableCollection of these Customer objects as a Table.  You now have the beginnings of a simple, in-memory database with which to store all the Customer objects when they arrive from the Cloud.

Start out by dragging another button on to MainPage.xaml and calling it Get Customers.  Double-click on this Button and add the following WebClient code to the click event:

try
{
    WebClient webClient = new WebClient();
    Uri uri = new Uri("
http://127.0.0.1:48632/service1.svc/customers");
    webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(OpenReadCompletedCustomers);
    webClient.OpenReadAsync(uri);
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

You’ll notice that it looks almost identical to the previous WebClient call except this time you’re just adding /customers to the end of service1.svc.  The beauty of the UriTemplate is that Microsoft makes it just that easy to call a REST service from WCF.  Since the above code created an event handler, paste this following code into the MainPage class to handle the callback:

void OpenReadCompletedCustomers(object sender, OpenReadCompletedEventArgs e)
{
    DataContractJsonSerializer ser = null;

    try
    {
        ser = new DataContractJsonSerializer(typeof(ObservableCollection<Customer>));
        Database.Instance.Customers = ser.ReadObject(e.Result) as ObservableCollection<Customer>;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

You’ll immediately see a bunch of squiggly lines telling you something is missing.  Add a reference to System.Servicemodel.Web and then add using System.Runtime.Serialization.Json; at the top in order to fix the problems with DataContractJsonSerializer.  Next add using System.Collections.ObjectModel; at the top to fix the ObservableCollection squigglies.  Give your solution a quick Rebuild to ensure that everything compiles.

In analyzing the new code I just had you add, you’ll notice the use of DataContractJsonSerializer which in this case is used to de-serialize JSON-encoded Customer objects that are downloading over the air.  It does this by casting them as ObservableCollection<Customer> which works because I had you copy that class from the AzureRestService project.  In a world of right-clicking to add a Service/Web Reference to consume SOAP web services, you never had to know what was going on under the covers to create an easy to use proxy.  You also never saw Visual Studio create hidden classes that looked just like the ones found on the server side so your client would have something to work with and so that intellisense worked. 

The last important line of code you see is setting the Customers table of your in-memory database equal to the de-serialization of the OpenReadCompletedEventArgs.  I think we’re ready to try out this code.  If all goes well, you’ll have a bunch of downloaded Customer data stored in an in-memory database on Windows Phone 7.

Set a breakpoint at the declaration of the DataContractJsonSerializer, hit F5, and click the Get Customers button!

WP75

Success looks like the picture above!  I hovered my mouse over Database.Instance.Customers and revealed that I was now storing Customers with Cities, CustomerId’s, PostalCodes, RouteId’s and StateProvinces for all to see in Visual Studio’s amazing debugger.

You are now consuming wireless-friendly WCF REST + JSON Services from both Windows Server and Windows Azure with data coming from SQL Server/SQL Azure.  Windows Phone 7 is connected to tiny, fast, efficient services designed to thrive in unreliable/slow wireless coverage.  You now know how to serialize/de-serialize .NET objects as JSON and you’ve also created your own in-memory database.

So what’s next?  In my next article, I’ll show you how to query this new in-memory database using LINQ and I’ll show you how to save the data in your local tables to Isolated Storage so you can keep using your apps even when the network has disappeared.

Keep coding and I’ll see everyone at Tech Ed in Berlin!

-Rob

Tags: , , , , , , , , , , , , , , , , , , ,

Category: Windows Phone 7

About the Author ()

A mobile strategist and cloud architect at Microsoft, Rob has spent his career as an entrepreneur, advisor, teacher, developer, speaker, and author of bestselling books on mobile and wireless technologies. A pioneer of the smartphone revolution, he drove the development of the mobile app ecosystem from its earliest days and co-founded the world’s first cloud-based mobile device management company.

Comments (5)

Trackback URL | Comments RSS Feed

  1. Bruce mcmillan says:

    Hi,

    thanks for the post.

    Did you ever try JSON datasets back from RIA service such a a parent / child stuff
    e.g.
    Sales order header
    SalesLine
    SalesLine
    SalesLine
    SalesLine
    SalesLine
    SalesLine

    when the data comes from objects, not entity datasets ?

    I seemed to have issues with the child lines not being retrieved correclty and wondered if you’d come across such a thing ?

    B….

  2. Bruce mcmillan says:

    Hi,

    thanks for the post.

    Did you ever try JSON datasets back from RIA service such a a parent / child stuff
    e.g.
    Sales order header
    SalesLine
    SalesLine
    SalesLine
    SalesLine
    SalesLine
    SalesLine

    when the data comes from objects, not entity datasets ?

    I seemed to have issues with the child lines not being retrieved correclty and wondered if you’d come across such a thing ?

    B….

  3. Jamie says:

    Great tutorials, much appreciated!

    Just wondering, any reason not to implement a single version of the data object(s) (either in a seperate class library or just in one of the projects) then reference the same object from both the WCF application and the WP7 app?

  4. Jamie says:

    It would appear that I have shown my almost total ignorance when it comes to Silverlight development with my previous commment.

    To answer my own question, Windows Class Libraries cannot be referenced from Silverlight projects as Silverlight is of course a different runtime.

    There’s some good discussion of the options in a couple of Stackoverflow questions:

    http://stackoverflow.com/questions/465460/sharing-c-code-between-windows-and-silverlight-class-libraries
    http://stackoverflow.com/questions/3637378/silverlight-class-library-to-windows-phone-7-class-library

Leave a Reply