A problem I’ve encountered at a customer I work for was very strange behavior regarding
the WSDL being generated by it’s service. The WSDL didn’t contain any class property, moreover it did contain private members of a class being exposed by the service.
Let’s have a look on a repro:
1. Here’s the class being exposed:
2. Here’s the class schema representation as being exposed in WSDL
3. Here’s the class as generated on client side
As seen from the WSDL and from the auto-generated client code, instead of getting the property SomeProperty of SerializableEntity you get the class's private field, which was the compiler-generated backing field (_x003C_SomeProperty_x003E_k__BackingField) of the automatic property.
Why did it happened?
SerializableAttribute indicates that all fields of the class marked Serializable can be serialized, including of course the private ones. However, it doesn’t say anything about the properties.
When getting the entity schema, the WCF invokes the the default formatter, having the class marked Srializable only (without DataContract) causes all fields to be serialized but no property is. Therefore we’ll see no property but private member.
That’s because the Serializable attribute aimed at binary serialization which serializes the data and not the methods. And data stored in fields and not in properties that are nothing more than methods accessing fields.
1. One solution is to have all service methods exposing the Serializable marked type use the XmlSerializerFormat simply by marking the method’s declaration at the service contract. This will cause the WSDL to be generated using XML serializer and will ignore the Serializable attribute and will serialize all public members including read-write properties.
This solution is good when the entities being exposed are in external DLLs or we can’t change their code for some reason.
2. At the exposed entities, add the DataContract attribute with DataMember attribute on each member we’d like to expose. After doing so, the DataContractFormat (which is the default format being used) will ignore the Serializable attribute and use only the DataMember attribute to serialize the schema.
Serializable attribute aimed at binary serialization, which uses all data in the class which stored in fields and not in properties. Therefore, colliding with DataContract serialization it produces an odd behavior of serializing all fields, including private ones and no property.
Using XmlSerializerFormat on the method declarations or DataContract on the very entity being exposed can solve the problem.