In the last post, we focused on the device side. We created a graphic rich web application using HTML 5 canvas, and browsed it in IE 9. This post focuses on the integration. That is, how to connect client applications to cloud services.

You can see the application lively on http://smalldemos.cloudapp.net/Html5Demos/SvgDemo.htm. The source code for this project can be downloaded from 1Code using this link: http://1code.codeplex.com/releases/view/51868#DownloadId=152535.

Working with SVG

The UI of this demo is much simpler than the demo in the last post. It simply draws a few rectangles, which looks like a 3D bar chart. The rectangles are rendered using SVG. You can refer to the IE 9 Developers Guide to get started with SVG.

SVG is a retained graphics API. It is much easier to use than canvas. It also supports declaratively creating shapes, just like Silverlight's XAML.

To embed SVG contents in an HTML document, you put a svg tag with the proper namespace:

    <svg id="mainSvg" version="1.1" xmlns="http://www.w3.org/2000/svg">

    </svg>

Then you can write xml tags to define the shapes. For example:

<rect fill="orange" stroke="black" width="150" height="75" x="50" y="25" />

This sample creates the elements dynamically in code based on the data returned by cloud services. To do so, you can use the familiar DOM API. For example:

            var rectangle1 = document.createElementNS(svgNamespace, 'rect');

            rectangle1.setAttribute('width', 100);

            rectangle1.setAttribute('height', height * 200);

            var x1 = 30 + i * 180;

            var y1 = 770 - height * 200;

            rectangle1.setAttribute('x', x1);

            rectangle1.setAttribute('y', y1);

            rectangle1.setAttribute('fill''rgb(' + red + ',' + green + ',' + blue + ')');

            rectangle1.setAttribute('stroke''black');

            rectangle1.setAttribute('stroke-width', 2);
            document.getElementById('mainSvg').appendChild(rectangle1);

As you can see, the code is not so straightforward as a typical Silverlight code, because JavaScript does not pre-define classes like Rectangle. This sample shows you the raw code. In real world, when working with SVG in code, it is recommended to use a library like jQuery SVG.

The advantage of SVG over canvas is it remembers the rectangle you just created. While not demonstrated in the sample, you can change the rectangle's properties (such as width and height) at a later time, and you can add mouse events on the rectangle. For example, when clicking the rectangle, you change its color. With an immediate graphics API (like canvas), it takes much more work to add interactives.

Connecting the application to the cloud

Now that you understand the basics of SVG, we can move to the cloud. The bars in the demo actually represents how dangerous a city is (in the New York state). The more dangerous a city is, the higher the bar becomes.

Obtaining professional data from Dallas

We do not store the data in our own database. Instead, we obtain the data from Dallas, a service hosted on Windows Azure. Dallas allows you to consume data provided by professional data providers. For example, our sample uses the "2006 and 2007 Crime in the United States" service provided by DATA.gov. Those professional data providers give you the most authority data.

The role of Dallas is: First, serves as a discovery portal for you to discover those services. Second, exposes the data to you using a single protocol: OData. So with Dallas, you don't need to learn a separate API to consume each service. You can use the familiar WCF Data Services API.

Please refer to http://www.microsoft.com/windowsazure/dallas/ for more information about Dallas.

Accessing Dallas data

Since Dallas exposes the data using OData protocol, you can use the standard REST API or a client library listed on http://www.odata.org/developers/odata-sdk (such as the JavaScript library and the Windows Phone library) to directly access the data in a client application. However, this approach exposes two problems: First, it may work for simple scenarios. But what if you want to write some custom business logics on top of the data? Where do you put the business logic? Duplicate them in all client applications? Second, you have to embed your Dallas account key in the client application, which is very dangerous.

So we will take a more SOA approach. We host a WCF REST service in Windows Azure. Then the client applications work with the WCF service. The service also performs some custom business logics. It calculates how dangerous a city is based on a simple rule (see the int sum = line of code for details).

        public List<CityCrimeWeight> GetCrimes()

        {

            List<CityCrimeWeight> results = new List<CityCrimeWeight>();

            datagovCrimesContainer svc = new datagovCrimesContainer(new Uri("https://api.sqlazureservices.com/Data.ashx/data.gov/Crimes"));

            svc.Credentials = new NetworkCredential("Account Key""
Your account key");

            var query = from c in svc.CityCrime where c.State == "New York" select c;

            int count = query.Count();

            int queried = 0;

            while (queried <= count)

            {

                var pagedQuery = query.Skip(queried).Take(100);

                queried += 100;

                foreach (var city in pagedQuery)

                {

                    CityCrimeWeight ccw = new CityCrimeWeight() { City = city.City, Population = city.Population };

                    int sum = city.MurderAndNonEgligentManslaughter * 10 + city.ViolentCrime * 7 + city.ForcibleRape * 7 + city.Arson * 7 + city.Burglary * 3 + city.MotorVehicleTheft * 3 + city.PropertyCrime * 1 + city.Robbery * 5 + city.LarcenyTheft * 1 + city.AggravatedAssault * 3;

                    ccw.Weight = (double)sum / city.Population;

                    results.Add(ccw);

                }

            }

            return results.OrderByDescending(c => c.Weight).Take(10).ToList();

        }

As you can see from the above code, accessing Dallas service is the same as accessing a normal WCF Data Services. First add a service reference to generate a client proxy. Then write a LINQ query, which will be translated to a corresponding URI.

One thing to note is Dallas forces a server side paging. One request returns up to 100 results. To obtain all results for a certain query, you should write a paging logic. You do so by invoking the Skip method to skip several pages, and invoke the Take method to specify the page size.

All requests to Dallas must be authenticated. You do so by setting the service context's Credential property.

One final note is our service doesn't return all data obtained from Dallas. We only return the city name, the population, and the weight we calculated using our custom business logic. This also helps to reduce the message size returned to the client. We host the service in the north central US data center, the same as Dallas. Data exchanged within the same data center is very fast (faster than disk I/O), and it doesn't charge for network consumption. So if you run the application locally in Development Fabric, you may find the performance is not so good as running in the cloud, because all Dallas data have to be downloaded to your local machine. In the cloud, Dallas data is transferred from Dallas VM to our own hosting VM between the same data center, which is very fast.

Hosting the WCF REST Services

Hosting a WCF REST Services in Windows Azure is the same as hosting it locally. First we define a service contract with the WebGet/Invoke attribute. Since we want to support a JavaScript client, we naturally return the data in JSON format:

    [ServiceContract]

    public interface ICrimeService

    {

        [OperationContract]

        [WebGet(UriTemplate = "/Crimes", ResponseFormat = WebMessageFormat.Json)]

        List<CityCrimeWeight> GetCrimes();

    }

When using .NET 4, WCF configuration is much simpler. You can use protocolMapping to define webHttpBinding as the default binding when the scheme is http. You can define a nameless endpoint behavior which will be applied to all endpoints. You don't need to explicitly define the services.

    <protocolMapping>

      <add binding="webHttpBinding" scheme="http"/>

    </protocolMapping>
    <behaviors>
      <endpointBehaviors>

        <behavior>

          <webHttp/>

        </behavior>

      </endpointBehaviors>

    </behaviors>

One problem in Windows Azure is certain configuration sections, such as protocolMapping, are missing in machine.config on the cloud machines. So you have to define them in web.config, otherwise the deployment will stuck in busy.

  <configSections>

    <sectionGroup name="system.serviceModel" type="System.ServiceModel.Configuration.ServiceModelSectionGroup, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">

      <section name="standardEndpoints" type="System.ServiceModel.Configuration.StandardEndpointsSection, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

      <section name="protocolMapping" type="System.ServiceModel.Configuration.ProtocolMappingSection, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

    </sectionGroup>

  </configSections>

Consuming the service from JavaScript client

You can use the standard jQuery ajax method to consume the service:

            $.ajax({ url: '../Services/CrimeService.svc/Crimes', success: createChart, dataType: 'json' });
        function createChart(data)

        {

            // Create a simple bar chart.

            $(data).each(function (i)

            {

                createRectangle(i, this.Weight, this.City);

            });

            $('#placeHolderDiv').hide();

        }

Creating a Windows Phone client

Now we have a service hosted in Windows Azure. We have a client application delivered from Windows Azure to a PC device, where a modern browser is running to render the chart. The same application should also work fine on a phone that supports SVG.

But not all phones support SVG. And even if SVG is supported, we need to modify the UI to make it more phone friendly. To take full advantage of a device, we still need to look into the native application development model.

On Windows Phone 7, an application can be created either using Silverlight or XNA. XNA is usually used for games, while Silverlight is used for other applications. So we choose Silverlight to implement our Windows Phone client.

We assume most Windows Azure developers are already familiar with Silverlight. So we won't go into the details on how the application is created. In addition, we cannot provide a live demonstration for the Windows Phone client... So instead, we will ship the source code in 1Code, together with the source code for the service and the HTML client.

Conclusion

This is the last post on IE 9/Windows Phone integration with Windows Azure. The key take away of this series is the cloud wants smarter devices. Both Windows 7 PC and Windows Phone 7 are smart devices. To exploit the full power of the devices in your applications, you should choose a modern platform with a modern technology. Then you connect the devices to the cloud, and bring the user a better experience.