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

by Nick 6. June 2010 02:05

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.

Tags: ,

Comments (18) -

6/6/2010 7:10:48 AM #

Simon

Link for the Hacked SharpZipLib does not work, can we have the wfc service code and full phone code please.
Thanks

Simon United Kingdom |

6/6/2010 11:14:59 AM #

nick

Link has been fixed for the hacked sharpziplib. There is no wcf service code other than what's above. It's a WCF Data Service - Visual Studio 2010 -> Add new item -> WCF Data Service. All the code you should need is in the blog post, other than the hacked SharpZipLib.

If you have any other issue, please don't hesitate to contact me.

nick Australia |

7/7/2010 1:30:45 PM #

Richard

I think you're incorrect about deserializing the JSON data, at least with the CTP.  The DataContractJsonSerializer class is not present in the System.Runtime.Serialization assembly in the CTP.

Richard United States |

7/7/2010 5:17:17 PM #

nick

Richard, The DataContractJsonSerializer is in that namespace, except you have to include a reference to the System.ServiceModel.Web assembly.

nick Australia |

7/26/2010 4:17:23 AM #

Nico

Your code doesn't work on the beta tools. Gzip compression is not available on silverlight !!

Nico France |

7/26/2010 6:26:22 AM #

nick

Nico, My apologies I haven't got around to updating this for the beta. The gzip library I used should work with the beta but you'll either have to wait for me to have time to update the code for it or do the update yourself :-)

nick Australia |

7/27/2010 6:12:38 AM #

Nico

What i am saying is that in SL you can't modify the Accept-Encoding headers. It throws exception
http://msdn.microsoft.com/en-us/library/system.net.webheadercollection%28VS.95%29.aspx

Nico France |

8/27/2010 9:40:57 AM #

mickey

I'm having the same problem.  

This line:
request.Headers["Accept-Encoding"] = "gzip, deflate";

returns an exception:
"The 'Accept-Encoding' header cannot be modified directly")

You also cannot do this:
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");

Anybody have a workaround?  Surely there must be some way of doing HTTP compression in Silverlight.

mickey United States |

8/11/2010 11:42:33 PM #

Retro Jordans

Your post really helped. It seems very interesting. Hope to read more about your Fashion tips. keep it up!

Retro Jordans United Kingdom |

8/12/2010 3:03:01 PM #

Rich

Hi Nick.

I am not able to get single file extraction working using ZipInputStream.GetNextEntry() in the modified-for-WP7 SharpZipLib.

None of the available System.Text.Encoding implementations seem to be working correctly for the ZipContants.ConvertToString operation.

If I just ignore that problem, opting for UTF8, it appears to not be correctly calculating the compressed size of an entry, so sanity checking fails in ZipInputStream.GetNextEntry (line 296).

Using ZipFile instead of ZipInputStream also does not work with IsolatedStorageFileStream (as Stream or as FileStream).  

Is this functionality planned for future implementations?

Rich United States |

8/14/2010 10:05:43 PM #

Sky

Hey Nick. Thanks for your port of #zip. I used it for quite a while in Phone7 and SIlverlight projects.

Ultimately I felt a full dedicated port was in order. I have ported .860 along with the tests and included IsolatedStorage aware implementations of ZipFile and FastZip.

You can find the announcement @ http://skysanders.net/subtext/archive/2010/08/14/release-sharpziplib.silverlight-for-sl-34-and-phone-7.aspx

Again, thanks for your work.

Sky United States |

8/16/2010 6:15:58 AM #

Rich

Ah ha!  The issue was the way I was writing to and from isolated storage.  Your modified sharpziplib works just fine.  Sorry for the confusion!  

Rich United States |

8/16/2010 6:27:41 AM #

Rich

Fixed my issue.  It wasn't the sharpzip library -- it was the way I was writing to and reading from isolated storage that was corrupting my compressed files.

Rich United States |

8/24/2010 9:55:18 AM #

Joel

Nico is right. It bombs trying to add the Accept-Encoding header.

Joel United States |

8/28/2010 12:23:08 AM #

nick

For everyone who has commented on this post, thank you for taking the time and I apologise that this scenario was broken by the super-smart people at Microsoft in the Windows Phone 7 beta developer tools. Luckily I've been able to find a work around - http://nicksnettravels.builttoroam.com/blogengine/post/2010/08/27/Windows-Phone-7-and-Compression-using-Accept-Encoding-Header.aspx   Let me know if this helps and addresses any issues you were having with accessing compressed data from IIS

nick Australia |

9/22/2010 4:07:24 AM #

Essay Paper

In the .NET Framework 4, there have been significant enhancements in Data Services from our .NET 3.5 SP1 release. This release has focused on providing new client and server side features for data service developers including improved Data Binding, Projections, Server Driven Paging, Count and Enhanced Blob support as well as many other improvements.

Essay Paper United States |

11/2/2010 2:38:44 AM #

Home Phone

Choose from our wide range of home phone packages specially designed to keep your budget low for home phone.

Home Phone United States |

11/18/2010 1:28:51 AM #

Software Development Consulting

This article was extremely interesting, especially since I was searching for thoughts on this subject last week

Software Development Consulting India |

Pingbacks and trackbacks (3)+

Powered by BlogEngine.NET 2.0.0.36

Automotive Theme by Car Leasing Experts

 

Page List