Today we had a very rough day, one of us had created a WCF REST service, and other one was trying to consume it in his IOS application, but he was not getting the correct response. We tested that call using Fiddler, could not find any problem in that. We tried very hard to troubleshoot why was that happening, but no luck.
We enabled WCF trace and message logging, although we could not log the actual message body, but we were able to review the headers of both calls. We found several differences other than the user-agent, and we experimented with most of them.
The most important header for us was content-type. We were passing application/xml and text/xml, acceptable. Are we using correct encoding? We were not sure. So we explicitly set that to UTF-8, without any success.
We also tested with other headers (connection: keep-alive, accept: text/html, application/xhtml+xml, */*, accept-encoding: gzip, deflate) without any luck.
We still were not able to see what data is received from the client, so were thinking about how to do that. Someone suggested to intercept the request/response traffic by injecting a HttpModule in the pipeline. We created a TrafficIntercepterModule for that purpose, and added it in. Now we were able to see the request body, found that request had all the required elements. So why still we are not getting the desired results.
Are we able to de-serialize this content back to our model? How should we test it. We have nested object in our request, we flattened it a bit, still not good.
Wait – does order of the elements has any impact on this. Hmmm, we were using default serialization, DataContractSerializer, and I have read somewhere that order of the elements does have an impact. Why not use XmlSerializer, as it does not follow those rules. voila, this change gave us the required results. I am not going in detail of merits and demerits of using one over other, but for now this started working for us.
When I was able to get sometime for myself, I tried to emulate it. I created a WCF application, hosting it in IIS and added two methods with same signature in a service. here is the contract for that service.
As you can clearly see that one operation does not have any format related attribute and other is explicitly assigned XmlSerializerFormat. If we don’t specify any format default is DataContractFormat.
A method can have either of the two attributes applied, but not both. Any operation that has neither applied uses the attribute applied to the containing class. If the containing class does not have either attribute applied, the DataContractSerializer is used.
Here are the model and service classes to support the above contract.
I used Fiddler to test both operations. First I used request XML as specified on the help page, that returned required results. However when I changed the order of the elements, it started to fail for operation “Authenticate1”, however what ever the order was used for “Authenticate2”, it always was successful.
Concluding it, when consuming WCF services from non-traditional clients either use the correct order of the elements, or apply the correct format if you want to give a free hand.