Why ASMX-Style WebReferences to WCF Services Don’t serialize Numbers
Based on a casual googling of this problem, it appears that some developers have spent days trying to figure out why an integer they set on the generated proxy field comes over the wire into the actual WCF service as ZERO. I didn’t spend days figuring it out, but it certainly did cause no end of annoyance and cursing until I did.
Let’s say you have a WCF service and for one reason or another (maybe your app is on a Handheld device and you cannot use “Add Service Reference”) you’ve set an ASMX – style “Add Web Reference”. Your code in the generated proxy Reference.cs class may look like this:
public int Quantity {
get {
return this.quantityField;
}
set {
this.quantityField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool QuantitySpecified {
get {
return this.quantityFieldSpecified;
}
set {
this.quantityFieldSpecified = value;
}
}
Note the extra field XxxSpecified with the XmlIgnore attribute that gets generated. If you do not set the QuantitySpecified Boolean field to “true”, your Quantity isn’t going to make it over the wire, period.
The extra XxxSpecified properties are added when you use ASMX-style references to a service that contains nullable value types, as ASMX does not directly support nullable types. The XxxSpecified must be true for ASMX to know that the value is specified in the XML, otherwise it will assume that the value is 'null'. So for example if your datetime value contained MinDate, how would you know that this signals 'null' ? The same is true for reading property values; if the XxxSpecified is false, then the related value must be considered to be 'null'.
The only exception to this is for strings. The documentation for this may be there, but I sure could not find it.
Twitter Tip
Recently I saw somebody I follow on Twitter announcing they had started to follow everybody who follows them as an “experiment”. I’m not sure I would advise that – because it could bring the signal-to-noise ratio to an unacceptable level. When I get an email that somebody is now following me on twitter, I go check them out. I look at their list of followers. If I don’t recognize too many names of people I’m already following, I usually decline to follow them unless I can clearly see that their content is of interest to me.
I’ve made a Twitter policy of only following people I’m interested in – fellow MVP’s, gurus in various disciplines such as Silverlight or WCF, and so on. The result is that I get a lot of very relevant content and very little “noise” – except for the inevitable “fembot” spammers – but it seems that Twitter has been doing an excellent job of putting those out of commission lately.
I also follow a few luminaries like Jeff Attwood, even though a lot of his Tweets are not that relevant – because of his occasional “Twingers” that really make you think!
I guess that's one good reason not to use nullable types for Web Services.
ReplyDeleteI've seen a lot of this from Java Services as well and it's painful because you end up having to set both the specified field and the value field. IMHO, the proxy should be smart enough to auotmatically set the specfied field when you se the Value on it but that's not the case so both have to be set.
So does using a WCF client proxy properly generate the nullable type? I vaguely remember running into this but can't remember whether WCF did the right thing or not.
@Rick,
ReplyDeleteYes I believe the WCF service reference proxy correctly handles this.
I've been working with some IBM "MAXIMO" product Oracle /JAVA backend services via AXIS/Websphere, and they generate the most horrific nested objects many of which have these "XXXSpecified" dealies. One good thing I can say - if I ever have to work with them again, I've already gone through the painful learning curve!