Ever since my last blog post where I demonstrated how to create lightweight WCF REST + JSON services for consumption by Windows Phone 7, I’ve received many requests from folks wanting to know how to do the same thing from Windows Azure.  Using Visual Studio 2010, the Azure Development Fabric and SQL Server, I will show you how to move this code to the cloud.

Fire up VS2010 and create a new cloud project (you’ll be prompted to download all the Azure bits if you haven’t done so already).

Azure1

Select WCF Service Web Role and move it over to your Cloud Service Solution.  Rename it to AzureRestService and click OK.

Azure2

You’ll then be presented with the default Service1.svc.cs SOAP web service that implements the IService1.cs Interface.  Needless to say, you’ll need to makes some modifications to these two files as well as Web.config if you want to be a true RESTafarian.

Azure3

In Service1.svc.cs, delete the GetDataUsingDataContract method but leave the GetData method since you’ll use it to perform an initial test.

Next, open IService1.cs and delete the GetDataUsingDataContract [OperationContract] as well as the CompositeType [DataContract].  You should be left with the simple GetData [OperationContract].

Open Web.config.  You’ll notice that it’s already pretty full of configuration items.  After the closing </serviceBehaviors> tag, tap on your Enter key a few times to give you some room to insert some new stuff.  Insert the following just below the closing </serviceBehaviors> tag and just above the closing </behaviors> tag as shown:

            <endpointBehaviors>
                <behavior name="REST">
                    <webHttp />
                </behavior>
            </endpointBehaviors>

This provides you with the all-important webHttp behavior that enables lean REST calls using HTTP Verbs.

Below the closing </behaviors> tag and above <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />, insert the following as shown:

            <services>
                <service name="AzureRestService.Service1">
                    <endpoint address="" behaviorConfiguration="REST" binding="webHttpBinding" contract="AzureRestService.IService1" />
                </service>
            </services>

Here is where we define our service name and contract.  It’s also where we point our behaviorConfiguration at the webHttp behavior you named “REST” and set the binding to webHttpBinding.

Now it’s time to decorate your interface’s [OperationContract] with a WebGet attribute and utilize a UriTemplate to give the Windows Phone 7 caller a web-friendly Uri to call.  So beneath [OperationContract] and above string GetData(int value);, squeeze in the following:

      [WebGet(UriTemplate = "/getdata?number={value}", BodyStyle = WebMessageBodyStyle.Bare)]

Since we want to call the GetData method via a GET request, we use WebGet and then we set our UriTemplate to something that anyone could access via their browser.  Lastly, we strip out all unnecessary junk by setting WebMessageBodyStyle.Bare.

It’s convenient that I mentioned using a browser to access this new REST service because that’s exactly how we’re going to test it.  Hit F5 in Visual Studio to fire up the Azure Development Fabric and start your Web Role.  Internet Explorer will come up and you’ll probably see an Error page because it points to the Root of your Role Site.  This is expected behavior.  In order to test the service, type the following in the IE address bar:

               http://127.0.0.1:81/service1.svc/getdata?number=5

This points to a loopback address on your computer with a port number of 81.  If your environment uses a different port, then just change what you pasted in as appropriate.  After the port number and “/”, you type in the name of the service you created which is service1.svc.  After the next “/”, you type the format you described in the UriTemplate.  You can type any Integer you wish and if everything works, the browser will display the following result:

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

With your test REST service working from your local Azure Development Fabric, it’s time to bring over the business logic from my last blog post where I showed you how to return Customer information from an on-premise WCF Service connected to SQL Server.  I don’t necessarily expect you to have a SQL Azure account so you’ll add a connection string to Web.config that points to a local SQL Server Express instance.  Don’t worry, you can swap this connection string out later to point to our awesome cloud database.  Beneath the closing </system.web> tag and above the <system.serviceModel> tag, insert the following:

<connectionStrings>
    <add name="ContosoBottlingConnectionString" connectionString="Data Source=RTIFFANY2\SQLEXPRESS;Initial Catalog=ContosoBottling;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>

This is the same connection string from the last blog post and you’ll definitely need to modify it to work with both your local SQL Server instance and SQL Azure when you’re ready to deploy.  Bear with me as the rest of this blog post will be a large Copy and Paste effort.

Open IService1.cs and add the following:

using System.Collections.ObjectModel;

and

[OperationContract]
[WebGet(UriTemplate = "/Customers", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
ObservableCollection<Customer> GetCustomers();

Open Service1.svc.cs and add the following:

using System.Web.Configuration;
using System.Collections.ObjectModel;
using System.Data.SqlClient;

 

and

//Get the Database Connection string
private string _connectionString = WebConfigurationManager.ConnectionStrings["ContosoBottlingConnectionString"].ConnectionString;

and

public ObservableCollection<Customer> GetCustomers()
{
    SqlConnection _cn = new SqlConnection(_connectionString);
    SqlCommand _cmd = new SqlCommand();
    _cmd.CommandText = "SELECT CustomerId, DistributionCenterId, RouteId, Name, StreetAddress, City, StateProvince, PostalCode FROM Customer";

    try
    {
        _cn.Open();
        _cmd.Connection = _cn;

        ObservableCollection<Customer> _customerList = new ObservableCollection<Customer>();

        SqlDataReader _dr = _cmd.ExecuteReader();
        while (_dr.Read())
        {
            Customer _customer = new Customer();
            _customer.CustomerId = Convert.ToInt32(_dr["CustomerId"]);
            _customer.DistributionCenterId = Convert.ToInt32(_dr["DistributionCenterId"]);
            _customer.RouteId = Convert.ToInt32(_dr["RouteId"]);
            _customer.Name = Convert.ToString(_dr["Name"]);
            _customer.StreetAddress = Convert.ToString(_dr["StreetAddress"]);
            _customer.City = Convert.ToString(_dr["City"]);
            _customer.StateProvince = Convert.ToString(_dr["StateProvince"]);
            _customer.PostalCode = Convert.ToString(_dr["PostalCode"]);

            //Add to List
            _customerList.Add(_customer);
        }
        return _customerList;
    } 
    finally
    {
        _cmd.Dispose();
        _cn.Close();
    }
}

As you can see, the only remaining error squigglies refer to the lack of the Customer class I discussed in the on-premise WCF project from the last blog post.  To add it, I want you to right-click on your AzureRestService project and select Add | Class and name the class Customer.

Azure4

Now I want you to paste the code below into this new class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;
using System.ComponentModel;

namespace AzureRestService
{
    [DataContract()]
    public class Customer : INotifyPropertyChanged
    {
        public Customer() { }

        private int customerId;
        private int distributionCenterId;
        private int routeId;
        private string name;
        private string streetAddress;
        private string city;
        private string stateProvince;
        private string postalCode;

        [DataMember()]
        public int CustomerId
        {
            get { return customerId; }
            set
            {
                customerId = value;
                NotifyPropertyChanged("CustomerId");
            }
        }

        [DataMember()]
        public int DistributionCenterId
        {
            get { return distributionCenterId; }
            set
            {
                distributionCenterId = value;
                NotifyPropertyChanged("DistributionCenterId");
            }
        }

        [DataMember()]
        public int RouteId
        {
            get { return routeId; }
            set
            {
                routeId = value;
                NotifyPropertyChanged("RouteId");
            }
        }

        [DataMember()]
        public string Name
        {
            get { return name; }
            set
            {
                name = value;
                NotifyPropertyChanged("Name");
            }
        }

        [DataMember()]
        public string StreetAddress
        {
            get { return streetAddress; }
            set
            {
                streetAddress = value;
                NotifyPropertyChanged("StreetAddress");
            }
        }

        [DataMember()]
        public string City
        {
            get { return city; }
            set
            {
                city = value;
                NotifyPropertyChanged("City");
            }
        }

        [DataMember()]
        public string StateProvince
        {
            get { return stateProvince; }
            set
            {
                stateProvince = value;
                NotifyPropertyChanged("StateProvince");
            }
        }

        [DataMember()]
        public string PostalCode
        {
            get { return postalCode; }
            set
            {
                postalCode = value;
                NotifyPropertyChanged("PostalCode");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String propertyName)
        {
            if (null != PropertyChanged)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

    }
}

As I mentioned in the last article, this class is a little overkill since it inherits from INotifyPropertyChanged and adds all the code associated with firing NotifyPropertyChanged events.  I only do this because you will use this same class in your Windows Phone 7 project to support two-way data binding.

The Customer table you’ll be pulling data from is shown in SQL Server Management Studio below:

Azure5

We’re now ready to roll so hit F5 in Visual Studio to debug this new cloud solution in the Azure Development Fabric.  When Internet Explorer comes up, type the following in the IE address bar:

            http://127.0.0.1:81/service1.svc/customers

You might be surprised to see the following dialog pop up instead of XML rendered in the browser:

Azure6

The reason you see this is because you’re returning the data objects in wireless-friendly JSON format.  Notice that the dialog say the Unknown file type is only 671 bytes.  This is a good thing.  Click the Save button and save this file to your desktop.

Now find the customer file on your desktop and rename it to customer.txt so you can view it in Notepad.  Double-click on this text box to reveal the tiny, JSON-encoded data in Notepad that you just looked at in the previous SQL Server Management Studio picture.

Azure7

Conclusion

If you followed me through this example and all the code executed properly, you now know how to build Windows Azure REST + JSON services designed to conquer those slow, unreliable, and highly-latent wireless data networks we all deal with all over the world.  When combined with my last article, both your on-premise and Windows Azure bases are covered with WCF.  The only thing left to do is sign up for an Windows Azure Platform account and move this Web Role and SQL Azure database to cloud.  In my next article, I’ll show you how to use the WebClient object from Silverlight in Windows Phone 7 to call these services.

Keep coding,

-Rob

Tagged on:                                                                                                                 

5 thoughts on “Windows Phone 7 Line of Business App Dev :: Moving your WCF REST + JSON Service to Windows Azure

  • October 20, 2010 at 6:02 am
    Permalink

    This is exactly what I have needed to get around the Linq issues in WP7 for oData. I have wasted about 4 weeks trying to work through those. I am trying to ready a WP7 medical app before the Nov. 8 launch and really need the client side architecture to finish this approach. Thanks,
    Bud Pinyan
    PinyanMed, Inc.

    Reply
  • October 20, 2010 at 6:05 am
    Permalink

    A second issue. I have been following you since your Teched video a few months ago and really like your isolated storage database approach. During that video, you mentioned that the code would be available. I have searched you site several times and have not been able to locate that code.
    Thanks,
    Bud Pinyan

    Reply
  • October 25, 2010 at 5:06 am
    Permalink

    I’m eagerly waiting for the next article about WP7 client for these services !

    Reply
  • Pingback: Windows Phone 7 – WP7 LOB App Dev | Xpert360 Ltd Development Blog

  • Pingback: Getting ready for the Windows Phone 7 Exam 70-599 (Part 1)

Leave a Reply