svcutil generated code missing parts - wcf

I have this:
"%PROGRAMFILES%\Microsoft SDKs\Windows\v7.0A\bin\svcutil.exe" ^
/noLogo /t:code /l:cs /mc /tcv:Version35 /ct:System.Collections.Generic.List`1 /n:*,MYNS ^
/config:MyServiceProxy.config ^
/out:ServiceProxy.cs ^
https://remote-service/ServiceA?wsdl
It generates classes, types and endpoint configurations as I expect.
When I add multiple endpoints ex:
"%PROGRAMFILES%\Microsoft SDKs\Windows\v7.0A\bin\svcutil.exe" ^
/noLogo /t:code /l:cs /mc /tcv:Version35 /ct:System.Collections.Generic.List`1 /n:*,MYNS ^
/config:MyServiceProxy.config ^
/out:ServiceProxy.cs ^
https://remote-service/ServiceA?wsdl https://remote-service/ServiceB?wsdl https://remote-service/ServiceC?wsdl
no endpoints in MyServiceProxy.config, and all the ServiceAWsClient() methods are missing from ServiceProxy.cs.
UPDATE: I removed the /i option, bec it made the classes internal.
UPDATE: I can now generate two .cs files, if I use the /serializer:DataContractSerializer option, I got the ServiceAWsClient() classes and without it I got the shared types.
Is there a way to get both the same time?
UPDATE: The file containing the ServiceAWsClient() classes still not good. Methods are missing paramteres. Why?
WSDL contains:
<xs:element name="service" type="tns:service"/>
<xs:element name="serviceResponse" type="tns:serviceResponse"/>
<xs:complexType name="service">
<xs:sequence>
<xs:element name="context" type="ns1:GenericContext" minOccurs="0"/>
<xs:element name="userData" type="ns2:UserData" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="serviceResponse">
<xs:sequence>
<xs:element name="resultContext" type="ns1:GenericResponseContext" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
svcutil generates:
public void service()
{
base.Channel.service();
}
when it should be:
public MYNS.GenericResultContext service(MYNS.GenericContext context, MYNS.ServiceA userData)
{
MYNS.service inValue = new MYNS.service();
inValue.context = context;
inValue.userData = userData;
MYNS.serviceResponse retVal = ((MYNS.ServiceA)(this)).service(inValue);
return retVal.resultContext;
}
ty!

The generation failed. svcutil does not support multi-targeting.
Infact the ClientBase (the proxy which is generated base class) can only access one endpoint.
You unfortunatly have to generate 3 diffrent proxies. In fact, theses proxies are encapsulating the actual channel (socket) which communicates with the service. So it seems that one proxy can handle only one endpoint

Related

Why is my WCF web service presenting this object in a different namespace with different field names?

The Context: I'm trying to integrate with DocuSign's Connect notification service. I've set up a WCF service with a method called DocuSignConnectUpdate which takes a DocuSignEnvelopeInformation as its only parameter, as specified by DocuSign. This DocuSignEnvelopeInformation object comes from a reference to their API, so that they can pass this object to my web service, and I know exactly what to expect. DocuSign asks for my service address and the namespace, which I have configured on their site.
The Problem: The XML that DocuSign sends is what I would expect. The DocuSignEnvelopeInformation and its children are in the namespace "http://www.docusign.net/API/3.0" and the element names match the object names:
<DocuSignEnvelopeInformation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.docusign.net/API/3.0">
<EnvelopeStatus>...</EnvelopeStatus>
</DocuSignEnvelopeInformation>
But my web service is expecting something different, in the wrong namespace, and with modified element names. This is how the DocuSignConnectUpdate method is defined in my WSDL:
<xs:element name="DocuSignConnectUpdate">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="DocuSignEnvelopeInformation" nillable="true" type="tns:DocuSignEnvelopeInformation"/>
</xs:sequence>
</xs:complexType>
</xs:element>
And this is how this is how the DocuSignEnvelopeInformation type is defined in my WSDL:
<xs:complexType name="DocuSignEnvelopeInformation">
<xs:sequence>
<xs:element xmlns:q1="http://schemas.datacontract.org/2004/07/System.ComponentModel" name="PropertyChanged" nillable="true" type="q1:PropertyChangedEventHandler"/>
<xs:element name="documentPDFsField" nillable="true" type="tns:ArrayOfDocumentPDF"/>
<xs:element name="envelopeStatusField" nillable="true" type="tns:EnvelopeStatus"/>
<xs:element name="timeZoneField" nillable="true" type="xs:string"/>
<xs:element name="timeZoneOffsetField" type="xs:int"/>
<xs:element name="timeZoneOffsetFieldSpecified" type="xs:boolean"/>
</xs:sequence>
</xs:complexType>
Element names like envelopeStatusField are the names of the private variables used in the auto-generated code. The public property names match the xml that DocuSign sends. The auto-generated code also tags each object with the correct docusign namespace using XmlTypeAttribute. So from looking at the auto-generated code, I would expect my service to be happy with the input, but the WSDL generated is different, as shown above, and my service fails to deserialize the xml.
Some Code:
The auto-generated declaration of DocuSignEnvelopeInformation:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.17929")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.docusign.net/API/3.0")]
public partial class DocuSignEnvelopeInformation : object, System.ComponentModel.INotifyPropertyChanged {
private EnvelopeStatus envelopeStatusField;
private DocumentPDF[] documentPDFsField;
private string timeZoneField;
private int timeZoneOffsetField;
private bool timeZoneOffsetFieldSpecified;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=0)]
public EnvelopeStatus EnvelopeStatus {
...
...
The OperationContract for the only method:
[SoapHeaders]
[ServiceContract(Namespace = "http:/MyNameSpace")]
public interface IDocusignEventListener
{
[OperationContract]
[FaultContract(typeof(ErrorMessageCollection), Action = Constants.FaultAction)]
string DocuSignConnectUpdate(DocuSignEnvelopeInformation DocuSignEnvelopeInformation);
}
The method that DocuSign calls
[ServiceBehavior(Namespace = "http:/MyNameSpace", ConfigurationName = "DocusignEventListener")]
public class DocusignEventListener : IDocusignEventListener
{
public string DocuSignConnectUpdate(DocuSignEnvelopeInformation DocuSignEnvelopeInformation)
{
...
return DocuSignEnvelopeInformation.EnvelopeStatus.EnvelopeID;
}
}
So, again, the question is why is the wsdl showing up this way? Why is the object different from the reference I pulled it from? And more importantly, can I fix it?
It is stunning how many hours I've spent on this, how many solutions I've tried, how many links I've followed, and how many SO answers I've read that did not answer my question before finally finding that the answer was sitting right here on SO for more than 2 years!
The root problem is that the DocuSignEnvelopeInformation object is being serialized and deserialized by DataContractSerializer by default. This essentially serializes the private member variables that make up the object in their local namespace instead of the public properties. Infuriatingly, this is the default serializer for WCF services. If the auto-generated code of the service application at least marked the sample methods with [DataContractFormat] explicitly, we would have a clue to follow, but it is just an invisible default that you have to divine somehow.
The solution is to mark each method with [XmlSerializerFormat] in the interface. This replaces DataContractSerializer with XmlSerializer as the serializer for the method parameters:
[SoapHeaders]
[ServiceContract(Namespace = "http://www.docusign.net/API/3.0")]
public interface IDocusignEventListener
{
[OperationContract]
[XmlSerializerFormat]
[FaultContract(typeof(ErrorMessageCollection), Action = Constants.FaultAction)]
string DocuSignConnectUpdate(DocuSignEnvelopeInformation DocuSignEnvelopeInformation);
}
And just like that, the public properties, with their declared namespaces and everything I need, are now serialized instead of the private data!
For my specific concern, to receive calls from DocuSign's Connect notification service, I still had one small namespace problem. The root level parameter, the DocuSignEnvelopeInformation, was still in the namespace of the method call. I’m not sure why. For now, I'm just putting the method call itself in the DocuSign API namespace (as you can see in the code sample above). The service now deserializes these calls correctly.

HTTPClient.PostAsync<T> with XmlMediaTypeFormatter serialization attributes being ignored

I'm working with an existing xsd which looks something like this (shortened for brevity):
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://www.mycompany.com/Widgets"
xmlns="http://www.mycompany.com/Widgets"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="Widget" type="WidgetDefinition" />
<xs:complexType name="WidgetDefinition">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
When you run this through xsd.exe, you get a class definition like:
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.mycompany.com/Widgets")]
[System.Xml.Serialization.XmlRootAttribute("Widget", Namespace="http://www.mycompany.com/Widgets", IsNullable=false)]
public partial class WidgetDefinition {
private string nameField;
public string Name {
get {
return this.nameField;
}
set {
this.nameField = value;
}
}
}
Fast forward ... I'm using HTTPClient to POST to a REST service. The code here is pretty straightforward.
var widget = new WidgetDefinition();
// do something here to hydrate widget
var httpClient = new HttpClient();
return httpClient.PostAsync<WidgetDefinition>(
uri, terminatedCall, new XmlMediaTypeFormatter());
On the receiving end, I want to take the request payload and convert it back to a WidgetDefinition object. If you examine the request content using:
request.Content.ReadAsStringAsync().Result
The xml looks like:
<WidgetDefinition xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://schemas.datacontract.org/2004/07/\">
...
Based on the XmlTypeAttribute and XmlRootAttribute attributes on the generated WidgetDefinition class, I expect this to look like:
<Widget xmlns:i=\"http://www.mycompany.com/Widgets\">
...
It appears that the XmlTypeAttribute and XmlRootAttribute attributes are ignored when the serialization is happening on the sending side.
Any clue what could be causing this?
EDIT: If I serialize this manually using XmlSerializer, it obeys the serialization attributes on the WidgetDefinition class. I think my issue has to do with the formatter being passed to the PostAsync call.
From this xmlns=\"http://schemas.datacontract.org/2004/07/\" it appears that your REST service is configured to use DataContractSerializer (the default in a WCF service) and not XmlSerializer.
You can configure your service to use XmlSerializer instead which should at least get you further along:
http://msdn.microsoft.com/en-us/library/ms733901.aspx

VB.NET Case Insensitive Web Reference enumeration Issue

I created a Web Reference (also tried Service Reference) to a WSDL that had the following node inside an xsd:
<xs:element name="filter">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element minOccurs="0" maxOccurs="unbounded" ref="condition" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="filter" />
</xs:choice>
<xs:attribute default="and" name="type">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="and" />
<xs:enumeration value="or" />
<xs:enumeration value="AND" />
<xs:enumeration value="OR" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute default="false" name="not" type="xs:boolean" />
</xs:complexType>
</xs:element>
When the client proxy class is created it produces this:
'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.225"), _
System.SerializableAttribute(), _
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=true, [Namespace]:="urn://wsc.acme.com/dm/2010/02/02")> _
Public Enum filterType
'''<remarks/>
[and]
'''<remarks/>
[or]
'''<remarks/>
[AND]
'''<remarks/>
[OR]
End Enum
This wouldn't build in a VB project because VB.NET is case insensitive. I tried deleting one set of and/or, but when the XML is created, it simply ignores the selected value. I also tried appending an X at the end of one the sets which also failed.
Is there a way to make this work? I also tried updating the XSD so it just had two values without success. The interesting thing to note is that default is set to "and" and while debugging it will set it to and, it doesn't actually produce the node attribute of it just generates .
You simply cannot have two enums with the same name. You can try setting the AllowMultiple attribute but the problem you are experiencing will still happen. My suggestion would be to remove the duplicate values in the original XSD and rebuild.

Tool or a way to create a DataSet.XSD from a Mapping C# .cs file or a NHibernate.hbm.xml file?

I need to create a DataSet.xsd file according to a NHibernate.hbm.xml file or a Class File. These are Mapping files and class files than we use to work with our DB.
You may ask me, why I do need a DataSet file, generating from a Nhibernate.hbm.xml file or a .cs file?
It's because we're using Crystal Reports, and we're using Frameworks, MVVM, INotifyPropertyChanged, NHibernate and after a lot of studying, for our case, would be better if we Convert an object while in executing time of program and use it to generate a report. If this tool exists, it will make easier, 'cause we have over 60, 70 columns per table in our DB. Since we're already with all these components working into our Project, it wouldn't make sense if we start to use sql queries to generate reports.
This tool, or 'the way to' create this DataSet file, need to read those file in these formats:
Nhibernate.hbm.xml file:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="PCT.Domain" namespace="Gerdau.PCT.Kernel.Domain">
<class name="Furnace" table="Furnace" lazy="false">
<id name="Id" column="Id_Furnace" type="Int64">
<generator class="Geraes.GLib.GDomainBasis.CustomTableHiLoGenerator, GLib.GDomainBasis" />
</id>
<property name="Name" column="Name" type="String" length="50" not-null="true"/>
<property name="Code" column="Code" type="Char" not-null="true"/>
<property name="Mill" column="Mill" type="String" length="2" not-null="true"/>
<property name="DischEnabled" column="Disch_Enabled" type="Char" not-null="true"/>
<property name="DischEnabledTemp" column="Disch_Enabled_Temp" type="Char" not-null="true"/>
<property name="ChargeEnabled" column="Charge_Enabled" type="Char" not-null="true"/>
<property name="ChargeEnabledTemp" column="Charge_Enabled_Temp" type="Char" not-null="true"/>
</class>
</hibernate-mapping>
CSharp .cs File:
public class Furnace : BaseEntity
{
public virtual String Name { get; set; }
public virtual Char Code { get; set; }
public virtual String Mill { get; set; }
public virtual Char DischEnabled { get; set; }
public virtual Boolean DischEnabledConv
{
get
{
return DischEnabled.ConvertYesNoToBoolean();
}
set
{
DischEnabled = ((Boolean)value).ConvertYesNoToBoolean();
}
}
public virtual Boolean DischEnabledTempConv
{
get
{
return DischEnabledTemp.ConvertYesNoToBoolean();
}
set
{
DischEnabledTemp = ((Boolean)value).ConvertYesNoToBoolean();
}
}
public virtual Char DischEnabledTemp { get; set; }
public virtual Char ChargeEnabled { get; set; }
public virtual Boolean ChargeEnabledConv
{
get
{
return ChargeEnabled.ConvertYesNoToBoolean();
}
set
{
ChargeEnabled = ((Boolean)value).ConvertYesNoToBoolean();
}
}
public virtual Boolean ChargeEnabledTempConv
{
get
{
return ChargeEnabledTemp.ConvertYesNoToBoolean();
}
set
{
ChargeEnabledTemp = ((Boolean)value).ConvertYesNoToBoolean();
}
}
public virtual Char ChargeEnabledTemp { get; set; }
public virtual ConfiguracaoForno MillConv
{
get
{
if (Mill == ConfiguracaoForno.SM.ToString())
return ConfiguracaoForno.SM;
if (Mill == ConfiguracaoForno.PM.ToString())
return ConfiguracaoForno.PM;
else
return ConfiguracaoForno.NN;
}
}
public override String ToString()
{
return "Forno " + Code + " (" + Name + "): Laminador " + MillConv;
}
}
I know it's an very specific case, but if you can show to us at least a way, it'll be of great help.
Best regards,
Gustavo
Edit:
Found a way to do it: using XSD.EXE, a internal Tool from Visual Studio, i've extracted the mapping from my assembly:
C:\>xsd / c /l:CS -t:Furnace <MyAssembly>.dll -o:"D:\Temp"
But now, when I do this:
D:\>xsd /c schema0.xsd
Results in these errors:
D:\Temp>xsd /c schema0.xsd
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 4.0.30319.1]
Copyright (C) Microsoft Corporation. All rights reserved.
Schema validation warning: Type 'char' is not declared, or is not a simple type.
Line 21, position 5.
Schema validation warning: Type 'http://microsoft.com/wsdl/types/:char' is not declared. Line 10, position 7.
Schema validation warning: Type 'http://microsoft.com/wsdl/types/:char' is not declared. Line 12, position 7.
Schema validation warning: Type 'http://microsoft.com/wsdl/types/:char' is not declared. Line 15, position 7.
Schema validation warning: Type 'http://microsoft.com/wsdl/types/:char' is not declared. Line 16, position 7.
Schema validation warning: Type 'http://microsoft.com/wsdl/types/:char' is not declared. Line 19, position 7.
Warning: Schema could not be validated. Class generation may fail or may produce incorrect results.
Error: Error generating classes for schema 'schema0'.
- The datatype 'char' is missing.
If you would like more help, please type "xsd /?".
Here's my generated schema.xsd:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import namespace="http://microsoft.com/wsdl/types/" />
<xs:element name="Furnace" nillable="true" type="Furnace" />
<xs:complexType name="Furnace">
<xs:complexContent mixed="false">
<xs:extension base="BaseEntity">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" />
<xs:element minOccurs="1" maxOccurs="1" name="Code" xmlns:q1="http://microsoft.com/wsdl/types/" type="q1:char" />
<xs:element minOccurs="0" maxOccurs="1" name="Mill" type="xs:string" />
<xs:element minOccurs="1" maxOccurs="1" name="DischEnabled" xmlns:q2="http://microsoft.com/wsdl/types/" type="q2:char" />
<xs:element minOccurs="1" maxOccurs="1" name="DischEnabledConv" type="xs:boolean" />
<xs:element minOccurs="1" maxOccurs="1" name="DischEnabledTempConv" type="xs:boolean" />
<xs:element minOccurs="1" maxOccurs="1" name="DischEnabledTemp" xmlns:q3="http://microsoft.com/wsdl/types/" type="q3:char" />
<xs:element minOccurs="1" maxOccurs="1" name="ChargeEnabled" xmlns:q4="http://microsoft.com/wsdl/types/" type="q4:char" />
<xs:element minOccurs="1" maxOccurs="1" name="ChargeEnabledConv" type="xs:boolean" />
<xs:element minOccurs="1" maxOccurs="1" name="ChargeEnabledTempConv" type="xs:boolean" />
<xs:element minOccurs="1" maxOccurs="1" name="ChargeEnabledTemp" xmlns:q5="http://microsoft.com/wsdl/types/" type="q5:char" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="BaseEntity">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="Id" type="xs:long" />
</xs:sequence>
</xs:complexType>
</xs:schema>
I appreciate for any help.
Gustavo
You're missing an XSD file.
UPDATE: Let's assume you're staying with xsd.exe. In this case, modify the import statement as following (I call this file XSD-1.xsd):
<xs:import namespace="http://microsoft.com/wsdl/types/" schemaLocation="XSD-2.xsd" />
Copy the content below in XSD-2.xsd file, in the same folder:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="http://microsoft.com/wsdl/types/" elementFormDefault="qualified" targetNamespace="http://microsoft.com/wsdl/types/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="guid">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="char">
<xs:restriction base="xs:unsignedShort" />
</xs:simpleType>
</xs:schema>
Run the xsd.exe with the following line:
xsd XSD-1.xsd /c
You should get an XSD-1.cs file and some warnings
If you want to use svcutil, you must have the XSD-2.xsd, otherwise it won't work; also, on the plus side you don't have to modify the XSD-1.xsd:
svcutil XSD-1.xsd XSD-2.xsd /dconly
It works fine, without any errors. I am running v4.

Effect of Soap message in Adding a new member in Data Contract

Adding new members in the Data contract are harmless for all versions of clients. Its a known fact.
I wanted to test this.
I created a Book Data Contract. Its first version had the following members.
public class Book
{
[DataMember(IsRequired = false)]
public long BookID;
[DataMember(IsRequired = true)]
public string Title;
[DataMember(IsRequired = false)]
public string Author;
}
The client was created for this version of Contract.
Then I added another member "Edition" to the Book and the new version of the Book is
public class Book
{
[DataMember(IsRequired = false)]
public long BookID;
[DataMember(IsRequired = true)]
public string Title;
[DataMember(IsRequired = false)]
public string Author;
[DataMember(IsRequired = false)]
public string Edition;
}
The newer version of the contract works flawlessly with the older vesion of client.
I wanted to Physically see the on wire soap message. I have enabled the client and server side message logging.
I understand that new member "Edition" would be taken as Nil and would be while serializing.
But on the client side message, I saw something strange, the following.
The soap envelop looks like this
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://www.8fingergenie.com/BookShop/CheckAvailability</Action>
<ActivityId CorrelationId="631f540a-915b-4203-8fd8-e251da2fab85" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">68a15797-124d-47f7-a85a-cf5c661e8011</ActivityId>
</s:Header>
<s:Body>
<CheckAvailability xmlns="http://www.8fingergenie.com/">
<book xmlns:d4p1="http://8fingergenie.com" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<d4p1:Author>Spensor Johnson</d4p1:Author>
<d4p1:BookID>1</d4p1:BookID>
<d4p1:Edition i:nil="true"></d4p1:Edition>
<d4p1:Title>Who Moved My Cheese</d4p1:Title>
</book>
</CheckAvailability>
</s:Body>
My question is how did the client with older version of Data contract know about edition while making communication? or am I missing something here.
Following is the structure of the client side Book's schema.
<xs:schema xmlns:tns="http://8fingergenie.com" elementFormDefault="qualified" targetNamespace="http://8fingergenie.com" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="Book">
<xs:sequence>
<xs:element minOccurs="0" name="Author" nillable="true" type="xs:string" />
<xs:element minOccurs="0" name="BookID" type="xs:long" />
<xs:element name="Title" nillable="true" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:element name="Book" nillable="true" type="tns:Book" />
It is not harmless for all clients. You could write a client that would fail if any members were added, deleted, or changed.
The fact that a client could be deliberately written to fail in that situation implies that it's possible to write a client which would inadvertently fail in the same situation.
On Further research I have found the following.
I was using Service reference in the client. The service reference by default creates the Data contract as type derived from IExtensibleDataObject. I didn't notice this would be the default.
So since the type is derived from IExtensibleDataObject, the new members from the other end is wraped inside the ExtensionDataObject. This is how the client was aware of the datacontract's new member.
Thank you for everyone who tried to help me.