I have WCF endpoint exposed as defined bellow,
<service name="MyApp.Server.Endpoint.Orange" behaviorConfiguration="MyTio.Server.Endpoint.OrangeBehavior">
<endpoint address="" binding="basicHttpBinding" contract="Host.Server.Contract.IMyAppApi" bindingNamespace="http://host.com/myapp">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
when I add a “Service Refrence” in .NET 3.5 we get the following class in the proxy which is perfectly fine:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="GetMemberBillersRequest", Namespace="http://schemas.datacontract.org/2004/07/Contract.MemberBillers")]
[System.SerializableAttribute()]
public partial class GetMemberBillersRequest : WCFClient.MyRequest {
[System.Runtime.Serialization.OptionalFieldAttribute()]
private int ApplicationIdField;
[System.Runtime.Serialization.OptionalFieldAttribute()]
private int ProductIdField;
[System.Runtime.Serialization.DataMemberAttribute()]
public int ApplicationId {
get {
return this.ApplicationIdField;
}
set {
if ((this.ApplicationIdField.Equals(value) != true)) {
this.ApplicationIdField = value;
this.RaisePropertyChanged("ApplicationId");
}
}
}
[System.Runtime.Serialization.DataMemberAttribute()]
public int ProductId {
get {
return this.ProductIdField;
}
set {
if ((this.ProductIdField.Equals(value) != true)) {
this.ProductIdField = value;
this.RaisePropertyChanged("ProductId");
}
}
}
}
the issue is when you add the reference to the same service but in .NET 2.0
you get the following proxy for the same contract:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.3082")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://schemas.datacontract.org/2004/07/Contract.MemberBillers")]
public partial class GetMemberBillersRequest : MyRequest {
private int applicationIdField;
private bool applicationIdFieldSpecified;
private int productIdField;
private bool productIdFieldSpecified;
/// <remarks/>
public int ApplicationId {
get {
return this.applicationIdField;
}
set {
this.applicationIdField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool ApplicationIdSpecified {
get {
return this.applicationIdFieldSpecified;
}
set {
this.applicationIdFieldSpecified = value;
}
}
/// <remarks/>
public int ProductId {
get {
return this.productIdField;
}
set {
this.productIdField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool ProductIdSpecified {
get {
return this.productIdFieldSpecified;
}
set {
this.productIdFieldSpecified = value;
}
}
}
both are identical except the proxy generated through .NET 2.0 has two additional fields:
productIdFieldSpecified and applicationIdFieldSpecified. the issue with these two fields are that if you don’t set the them manually to true their corresponding fields (ApplicationId, ProductId ) will not be serialized and passed to the server!
can someone please explain to me what is happening here?
EDIT:
I have found that this is only happening for int types, not strings!
here is the data contract for this operation
[DataContract]
public class GetMemberBillersRequest : MyRequest
{
[DataMember]
public int ApplicationId { get; set; }
[DataMember]
public int ProductId { get; set; }
}
This is the expected behavior, and has been that way since .NET 1.0. You’ll see that for any primitive type which is optional in the schema – either an attribute with use=”optional”, or an element with minOccurs=”0″.
If the attribute or element were missing, then the generated property cannot be set to null. Instead, the *specified field is set to false in that case. Check that field before you decide whether the “real” one is present or not.
Similarly, if you want to set the main property, then you have to set the *specified property to true, otherwise it won’t get sent.
I’m sure you know, but I’m adding this for future readers: Yes, there are nullable types now. However, development on ASMX web services slowed down considerably with the advent of WCF. It does not surprise me that nullable properties were never implemented for primitive types.
Also, be aware of this: Microsoft: ASMX Web Services are a “Legacy Technology”.