Thursday 28 February 2008

WCF Web Services - Serialization of Automatic Properties

After attending the Heroes Happen {2008} event, I put together a little 'web services comparison' quick comparison as a "proof of concept" for my team at work.
The basic premise was to show an ASP.NET page using the AJAX ScriptManager consuming JSON objects served by both 'traditional' ASMX web services and Windows Communication Foundation (.SVC) web services in client-side Javascript. Creating JSON-enabled WCF services in .NET 3.5 was very helpful in getting it working quickly.

It was a pretty simple example - summarised in this graphic:

I built then ASMX first, then "ported" the resulting code to WCF. Everything worked pretty much as expected, until I got to the Javascript objects that WCF sent to the client. The objects seemed to load OK, but none of the fields/properties that I expected were present! At first I couldn't figure out what the problem could be - here's a look at the C# class definition - can you see the problem?

The same underlying C# class was being used in both ASMX & WCF, so it was difficult to imagine why ASMX worked and WCF didn't. Confused, I stepped into the Javascript using Firebug... at first, it wasn't immediately obvious to me why the properties had become <Code>k__BackingField, <Id>k__BackingField, etc in Javascript.

Footheory's post on Automatic Properties jogged my memory on how the compiler 'deals with' Automatic Properties... so the WCF JSON serializer is (for some reason) emitting the underlying field names whereas ASMX seems quite happy to emit the 'intended' name.

The fix was simple - add the WCF-specific DataMember attribute to the properties...

...and voila! they are again emitted in JSON as Code, Id, Price, etc.

It's probably easy to track down (now that Microsoft has made the source-code available) why this is happening; but for now I'm just happy it was an easy (if slightly unintuitive) fix. If you are converting ASMX web services to WCF and find BackingField popping up unexpectedly in your classes, adding the DataMember and DataContract attributes might just restore your sanity.

EDIT 7-May-08: I haven't gotten around to adding a Silverlight 2.0 example, but the concepts are all covered in Tim Heuer's Making use of your JSON data in Silverlight post.