Over a million developers have joined DZone.

WCF Data Services with Windows Phone - bandwidth requirements measured

Evolve your approach to Application Performance Monitoring by adopting five best practices that are outlined and explored in this e-book, brought to you in partnership with BMC.

In connection with testing Synchronization between a SQL Server Compact database on Windows Phone 8 and a SQL Server database (via a WCF Data Services service hosted in IIS), I have done some interesting observations regarding bandwidth requirements, that I would like to share.

I am testing against the Chinook sample database, by downloading the entire PlaylistTrack table (8715 rows) to the device via my WCF Data Services service. On the server side, I am using the latest release version of the WCF Data Services server components, version 5.3.0.Version 5.1 or later includes the newer lightweight JSON format (just to compare I am also including sizes for the previous JSON format)

On the server side, I have created a ASP.NET Web Application with a WCF Data Service, that exposes the Chinook database on my SQL Server via an Entity Framework DbContext. The power of WCF Data Services is that this requires basically no code to configure. I have configured my service like this:

    public class SyncService : DataService<ChinookEntities>
    {
        // This method is called only once to initialize service-wide policies.
        public static void InitializeService(DataServiceConfiguration config)
        {
            config.UseVerboseErrors = true;
            //config.SetEntitySetAccessRule("TrackPurchases", EntitySetRights.WriteAppend);
            config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
        }
    }


In order to access the IIS Express hosted service from my Windows Phone 8 emulator, I followed the instructions here: http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj684580(v=vs.105).aspx 


To measure the size of the payload, I am using Fiddler2, by following the instructions here: http://blogs.msdn.com/b/fiddler/archive/2010/10/15/fiddler-and-the-windows-phone-emulator.aspx


The WCF Data Services team also supply a WCF Data Services client for Windows Phone, that can take advantage of a Service Reference, but this client has some severe limitations, that affects bandwidth consumption in a bad way: It only supports the XML based ATOM format, but you can enable compression, as described here: http://blogs.msdn.com/b/astoriateam/archive/2011/10/04/odata-compression-in-windows-phone-7-5-mango.aspx 


On the client side, I am simply using HttpWebRequest to call the REST url, and including support for gzip via the ICSharpCode.SharpZipLib library (for example http://nuget.org/packages/SharpZipLib-WP7/ )


Here is the implementation of the WebClient:

        static public async Task<T> GetData<T>(Uri uri, bool useJson = true, bool version3 = true, bool compress = true)
        {
                //uri = new Uri(uri.AbsoluteUri + "&format=json");
                HttpWebRequest client = WebRequest.CreateHttp(uri);
                {
                    if (compress)
                        client.Headers[HttpRequestHeader.AcceptEncoding] = "deflate, gzip";
                    if (version3)
                    {
                        client.Headers["MaxDataServiceVersion"] = "3.0";
                    }
                    else
                    {
                        client.Headers["MaxDataServiceVersion"] = "2.0";
                    }
                    if (useJson)
                        client.Accept = "application/json";
                    
                    using (WebResponse response = await client.GetResponseAsync())
                    {
                        string result = await response.GetResponseText();

                        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
                        T resultType;
                        using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(result)))
                        {
                            resultType = (T)serializer.ReadObject(stream);
                        }
                        return resultType;
                    }
                }
        }

        public static async Task<string> GetResponseText(this WebResponse response)
        {
            using (
            Stream stream = response.IsCompressed()
                                   ? new GZipInputStream(response.GetResponseStream())
                                   : response.GetResponseStream())
            {
                using (var reader = new StreamReader(stream))
                {
                    return await reader.ReadToEndAsync();
                }
            }
        }

        public static bool IsCompressed(this WebResponse response)
        {
            return Regex.IsMatch((response.Headers["Content-Encoding"] ?? "")
                                     .ToLower(), "(gzip|deflate)");
        }


(I am using Microsoft.Threading.Tasks.Extensions.dll to implement GetResponseAsync)


I am using DataContext classes generated by my SQL Server Compact Toolbox for deserialization, with a small addition - I have added this attribute to all EntitySet<T> and EntityRef<T> properties (this will be included in the next Toolbox release):


[global::System.Runtime.Serialization.IgnoreDataMember]


I am calling the following URL: http://<MyIP>:2065/SyncService.svc/PlaylistTracks


This is my test code:

/ATOM-XML
await WebClient.GetData<PlaylistTrackRoot>(uri, false, false, false);
//Verbose json
await WebClient.GetData<PlaylistTrackRoot>(uri, true, false, false);
//Verbose json + gzip
await WebClient.GetData<PlaylistTrackRoot>(uri, true, false, true);
//Plain json
await WebClient.GetData<PlaylistTrackRoot>(uri, true, true, false);
//Plain json + gzip
await WebClient.GetData<PlaylistTrackRoot>(uri, true, true, true);

public class PlaylistTrackRoot { public List<PlaylistTrack> value { get; set; } }

And finally the unbelievable numbers for the download of the entire PlaylistTrack table with 8715 rows (remember, that ATOM is the default WCF Data Services client format)


Payload type Body size (bytes)
ATOM-XML 9.322.665 (100 % – default DS client implementation)
JSON (verbose) 5.016.977 (54 %)
JSON (verbose) + gzip 328.410 (3,5 %)
JSON (plain) 790.845 (8,5 %)
JSON (plain) + gzip 43.023 (0,5 %)

So before you decide to use WCF Data Services (a very powerful technology) remember: With great power comes great responsibility.



Learn tips and best practices for optimizing your capacity management strategy with the Market Guide for Capacity Management, brought to you in partnership with BMC.

Topics:

Published at DZone with permission of Erik Ejlskov Jensen, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}