.NET Framework Developer Center > .NET Framework Forums > Windows Communication Foundation (WCF) > WCF proxy data class duplication bug - generating client proxy for non-WCF service

Answered WCF proxy data class duplication bug - generating client proxy for non-WCF service

  • Monday, January 25, 2010 12:54 PM
     
     

    I am attempting to use WCF to generate a proxy and supporting data classes for a Java-based set of web services, but the generated set of data classes contain duplicates class definitions. 

     

    The generated WSDL for the service defines types in three different namespaces (in separate schemas) with some types partly composed from types in other namespaces.  It also includes 'name' attributes for many more of the elements than are created in a ‘classic’ .Net generated WSDL.

     

    By creating a dummy 'classic' .Net web service and then manually editing the WSDL to include aspects of the Java service I have identified two aspects that, when found in combination in a WSDL, cause this behaviour to occur in the WCF proxy class generation.

     

    Firstly, when I specified that certain .Net types should be serialised in different XML namespaces (via the XmlType attribute in the C# code) the .Net WSDL generator added <import/> elements to each schema that contained types that were composed of types in another schema.  The Java-based web service WSDL does NOT include these 'import' elements.

     

    Example of import element missing from Java-based service’s WSDL:

        <s:schema elementFormDefault="qualified" targetNamespace="http://TestClassicSvc.mynamespace.com/">

          <s:import namespace="http://MySvcTypes.TestClassicSvc.mynamespace.com/" />

    ...

        </s:schema>

     

    Secondly, the Java-based schema defines WSDL <fault/> elements with name attributes e.g.:

      <wsdl:portType name="AnimalServiceSoap">

        <wsdl:operation name="GetSnake">

          <wsdl:input message="tns:GetSnakeSoapIn" />

          <wsdl:output message="tns:GetSnakeSoapOut" />

          <wsdl:fault name="AnimalServiceException" message="tns:AnimalServiceException" />

        </wsdl:operation>

    ...

      </wsdl:portType>

     

    Individually these do not cause the WCF proxy generator (service reference) any issues, but combined cause the generation of duplicate types.

     

    Incidentally these features do not cause any proxy generation issues for the 'classic' .Net proxy generator (web reference).                                       

     

    I can't see any possible reason for this behaviour so I am assuming that this is a bug.  Does anyone know of a fix or a workaround?

Answers

All Replies

  • Monday, January 25, 2010 1:08 PM
     
     

    To give an example of the generated C# code, here is a type defined in the test WSDL I created to replicate the problem:

          <s:complexType name="Animal">

            <s:sequence>

              <s:element minOccurs="0" maxOccurs="1" name="Name" type="s:string" />

            </s:sequence>

          </s:complexType>

     

    This class is generated for the WSDL regardless of whether imports elements are present or whether fault elements are named:

        [System.Diagnostics.DebuggerStepThroughAttribute()]

        [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]

        [System.Runtime.Serialization.DataContractAttribute(Name="Animal", Namespace="http://MySvcTypes.TestClassicSvc.mynamespace.com/")]

        [System.SerializableAttribute()]

        [System.Runtime.Serialization.KnownTypeAttribute(typeof(AnimalWSDLClient.AnimalSvc2.Donkey))]

        [System.Runtime.Serialization.KnownTypeAttribute(typeof(AnimalWSDLClient.AnimalSvc2.Snake))]

        public partial class Animal : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {

           

            [System.NonSerializedAttribute()]

            private System.Runtime.Serialization.ExtensionDataObject extensionDataField;

           

            [System.Runtime.Serialization.OptionalFieldAttribute()]

            private string NameField;

           

            [global::System.ComponentModel.BrowsableAttribute(false)]

            public System.Runtime.Serialization.ExtensionDataObject ExtensionData {

                get {

                    return this.extensionDataField;

                }

                set {

                    this.extensionDataField = value;

                }

            }

           

            [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)]

            public string Name {

                get {

                    return this.NameField;

                }

                set {

                    if ((object.ReferenceEquals(this.NameField, value) != true)) {

                        this.NameField = value;

                        this.RaisePropertyChanged("Name");

                    }

                }

            }

           

            public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

           

            protected void RaisePropertyChanged(string propertyName) {

                System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;

                if ((propertyChanged != null)) {

                    propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));

                }

            }

        }

     

     

    When imports elements are not present in the schema definitions and fault elements are named this second partial class is generated for the type:

        /// <remarks/>

        [System.Xml.Serialization.XmlIncludeAttribute(typeof(Donkey))]

        [System.Xml.Serialization.XmlIncludeAttribute(typeof(Snake))]

        [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.4016")]

        [System.SerializableAttribute()]

        [System.Diagnostics.DebuggerStepThroughAttribute()]

        [System.ComponentModel.DesignerCategoryAttribute("code")]

        [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://MySvcTypes.TestClassicSvc.mynamespace.com/")]

        public partial class Animal : object, System.ComponentModel.INotifyPropertyChanged {

           

            private string nameField;

           

            /// <remarks/>

            [System.Xml.Serialization.XmlElementAttribute(Order=0)]

            public string Name {

                get {

                    return this.nameField;

                }

                set {

                    this.nameField = value;

                    this.RaisePropertyChanged("Name");

                }

            }

           

            public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

           

            protected void RaisePropertyChanged(string propertyName) {

                System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;

                if ((propertyChanged != null)) {

                    propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));

                }

            }

        }

  • Tuesday, January 26, 2010 10:48 PM
     
     
    One idea is to generate xml serializer contracts in wcf.

    Try to generate the wcf proxy using svcutil.exe and give it the flag to generate using the xml serializer.

    http://webservices20.blogspot.com/
    WCF Security, Performance And Testing Blog
  • Wednesday, January 27, 2010 6:25 AM
    Moderator
     
     Answered
    Hi Max,

    As Yaron suggested, you can use svcutil.exe to generate .NET datacontract types that conform to XML serializer format.  e.g.

    svcutil.exe /target:code /dataContractOnly /serializer:XmlSerializer /importXmlTypes  [your xsd file's path]

    here is a former thread which mentioned this:

    #Generate bitwise Enum from XSD starting with 0
    http://social.msdn.microsoft.com/Forums/en/wcf/thread/e0386278-a528-4e93-a49c-174d6c10465f




    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
  • Monday, March 01, 2010 1:39 PM
     
     
    Hi Steven,

    Generating the classes using svcutil with the XmlSerializer option did the trick.

    Thanks for your help,

    Max