Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different behavior between 'Service Reference' and 'Web Reference'

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; }
}
like image 255
kay.one Avatar asked Jun 25 '26 17:06

kay.one


2 Answers

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”.

like image 110
John Saunders Avatar answered Jun 28 '26 05:06

John Saunders


It would be helpful to see your service code. I haven't used web service reference for a while but my guess is that if those fields are not optional add a IsRequired = True to your DataMemeber attribute and regenrate the proxy.

like image 28
softveda Avatar answered Jun 28 '26 05:06

softveda



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!