Windows Phone 7 Data: Json WCF Data Service with IIS 7 Compression

Today I was thinking about the way I consume data within my Windows Phone 7 applications, specifically how I can get a large amount of data into my application. Attempting to send 100Mb worth of uncompressed data across the wire when I could send the same thing compressed at around 25Mb wasn’t really appealing to me. This got me thinking…. “how did I do this on Windows Mobile?”…. surprisingly the answer is blindingly obvious: IIS  compression. In this post I’ll walk you through exposing your data via a WCF Data Service, enabling IIS compression (for IIS 7) and then how you can leverage this on the client side.

Let’s start by creating a simple WCF Data Service to consume:

WCF Data Service

In an ASP.NET project, create a new ADO.NET Entity Data Model, mine is called YoLoModel.edmx (YoLo stands for You only Live once, which was the name of the sample application I built as part of my Remix Australia presentation last week).

image

Next add a new WCF Data Service, and fill in the blanks with the name of your data context (In my case it’s YouOnlyLiveOnceEntities) and enable read access – you should come back later and tighten security!!

using System.Data.Services;

namespace CompressedService
{
    public class YoLoData : DataService<YouOnlyLiveOnceEntities>
    {
        public static void InitializeService(IDataServiceConfiguration config)
        {
             config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
        }
    }
}

At this point you should run up your ASP.NET project to make sure you get data when you view the data service. You should also make sure that your project is running on IIS, rather than using the Visual Studio Development Server. To do this go to Web tab of the project properties and change to “Use Local IIS Web server” (you need to hit the Create Virtual Directory to create the virtual directory so your application will run on IIS, and don’t forget to save the project properties). In my case IIS is running on port 8080 – this has no bearing on being able to use compression, just happens to be how I have IIS configured on my development machine.

image

Test this using either the browser or Fiddler.

image

IIS Compression

Setting up IIS 7 Compression isn’t that difficult once you know what to do. Start by using either the Web Platform Installer  or Programs and Features. Locate and check the box next to Dynamic Content Compression and hit Install – this adds the module to support dynamic compression into IIS.

image

Next, open up IIS Manager and locate your ASP.NET application. From the Feature View select Compression and then ensure both static and dynamic compression is enabled.

image

Next you have to enable dynamic compression for specific mime-types. Make sure you have the Server node (not your virtual directory or the web site nodes) selected and then select the Configuration Editor from the Feature View.

image

Locate the webServer/httpCompression node and find the dynamicTypes list.

image

Add any missing mime-types to cover SOAP, ATOM, JSON etc (you might as well enable them whilst you’re there). Whilst there is a trade off between performance and compression, dynamic compression only happens when the client requests it, so I’d turn it on for these mime-types and then make sure the clients only use compression appropriately (it’s up to you how you do this).

image

Don’t forget to hit the Apply button!!!

Don’t forget to RESTART IIS, make sure all your web processes restart otherwise you won’t see compressed output.

image

Now, go to Fiddler and use the Request Builder tab to create a GET request. I this case I’m requesting the url http://nickwp7dev:8080/CompressedService/YoLoData.svc/Patients. You need to specify the following headers:

Accept: application/json       -       This will cause WCF Data Services to give you the output in json format which is much trimmer than the bloated xml it usually generates. If you do want to work with xml then you can omit this header.

Accept-Encoding: gzip, deflate       -       This is what tells IIS to generate compressed data.

When you Execute this request you should see that Fiddler detects compressed data – If you don’t then go back and make sure you’ve hit Apply and restarted IIS as this seems to be the problem I came up against when experimenting with this.

image

If you click the yellow bar, Fiddler is kind enough to decompress the data so you can see the json output (or xml if you’ve omitted the Accept header).

image

Windows Phone

Right, so that’s the server side done. Now you need to implement decompression on the client. Unfortunately, unlike true rich client technologies such as WPF or WinForms, Silverlight and Windows Phone are somewhat crippled when it comes to dealing with data. However, with a little help you can work with the data quite easily.

In order to decompress the data coming from IIS I use SharpZipLib. Well actually I used a slightly hacked together version of it. Essentially there are things that need to be updated to be compatible with Silverlight/Windows Phone.

Hacked SharpZipLib for Windows Phone available here

Once you have SharpZipLib, decompressing the data is relatively straight forward:

using System;
using System.IO;
using System.Net;
using System.Windows;
using ICSharpCode.SharpZipLib.GZip;
using Microsoft.Phone.Controls;

namespace WindowsPhoneApplication1
{
    public partial class MainPage : PhoneApplicationPage
    {
        public MainPage()
        {
            InitializeComponent();

            SupportedOrientations = SupportedPageOrientation.Portrait | 
                                     SupportedPageOrientation.Landscape;
        }

        private void DisplayDataButton_Click(object sender, RoutedEventArgs e)
        {
            var request = HttpWebRequest.Create("http://nickwp7dev:8080/CompressedService/YoLoData.svc/Patients");
            request.Headers["Accept"] = "application/json";
            request.Headers["Accept-Encoding"] = "gzip, deflate";
            request.BeginGetResponse(RequestCallback, request);
        }

        void RequestCallback(IAsyncResult response)
        {
            var request = response.AsyncState as HttpWebRequest;
            var resp = request.EndGetResponse(response);
            var strm = resp.GetResponseStream();

            string data;
            using (var gzip = new GZipInputStream(strm))
            using(var reader = new StreamReader(gzip))
            {
                data = reader.ReadToEnd();
            }

            this.Dispatcher.BeginInvoke(()=>{
                this.DataText.Text = data;
            });
        }
    }
}

Run this, an there you go – compressed data from IIS 7 to Windows Phone!

image

Don’t forget you can use the json deserializer to then parse this into objects.

Leave a comment