I usually use 2 types of endpoints when using WCF: SOAP for server - server communication, and REST/JSON for browser – server service calls. But yesterday, while trying to debug some POST & PUT HTTP calls in Fiddler, I decided to use a REST/XML endpoint. After all, POX is a bit easier on the eyes than JSON, and this would give me an opportunity to test my XML endpoints, which I had created but never used.
Of course all I got were HTTP 400 responses – Method not allowed. The call would fail before ever reaching the service, and therefore was probably related to some DataContractSerializer exception.
My first thought was to use the .Net source code and inspect was going on inside WCF. I had been using the “Enable .Net Source Stepping” feature of VS 2008 for a while, and it had helped immensely for various System.Web & System.Net issues. Unfortunately, I found out WCF libraries (System.ServiceModel etc…) are not included. I sent a quick not to Scott Guthrie (who posted a year ago that those libraries would be coming soon) asking about for an ETA, and he was kind enough to forward my request to Bob Dimpsey, but I haven’t heard back yet (EDIT: Bob did get back to me last night, it looks like this will be coming out soon, but no ETA yet). So for now, no WCF source code.
Next I found some resources on how to configure WCF tracing. I configured the diagnostics to trace to the main output output window and finally figured out what was going on.
It turns out the DataContractSerializer was requiring a namespace in my message’s XML contents. Duh. I had forgotten to define the xml namespace in the DataContract. I fixed the problem, changed the message to added the xmlns attribute to the root of my xml data, and things started working.
Well, sort of. Some of my properties were missing in the deserialized object. After looking a bit deeper, it turns out DataContractSerializer forces specific ordering of your XML elements. When adding the DataMember attribute, there’s a way to specify an “Order” property. If that property is not defined, DataContractSerializer defaults to alphabetized names. This means if your class has 2 properties Name, FirstName defined, your XML data will need to list <FirstName /> <LastName /> – ordered alphabetically. Apparently it has something to do with performance and versioning.
Once I made sure my elements were alphabetized, I was able to text my REST services using XML without any problem.
2 comments:
Useful info, thanks. Is there anyway to have the dataserializer ignore the ordering?
Not that I know, and that's one of the main reason we use JSON serialization for all our WCF calls.
One option would be to swap the serializer to XmlSerializer instead of DataContractSerializer. But that means decorating your cont4racts with XmlSerialzer attributes.
More info here:
http://msdn.microsoft.com/en-us/library/ms733901.aspx
Post a Comment