I'm facing a strange issue with WCF serialization. My project has a type named RefEntity which has a property of another type named RefDomain. A WCF service defines two methods, one takes type RefEntity as parameter, and another takes type RefDomain as parameter.
The method with the RefDomain parameter doesn't seem to serialize the object as all the properties have null value on the service side. Whereas, the method with RefEntity parameter (and RefDomain as a member) works as expected (RefDomain member is serialized as expected).
What am I missing here?
public class RefDomain
{
private string name;
private RefDomain parent;
private Type entityType;
public string Name
{
get => this.name;
protected set => this.name = value;
}
public RefDomain Parent
{
get => this.parent;
protected set => this.parent = value;
}
public Type RefEntityType
{
get => this.entityType;
protected set => this.entityType = value;
}
}
Your properties have protected setters, and
DataContractSerializerwill only serialize properties that are fully public, unless marked with data contract attributes.Once you apply the necessary
[DataContract]and[DataMember]attributes, you will discover a second problem, namely thatDataContractSerializercannot serialize values of typeSystem.Type. (Demo fiddle #1 here). To serialize yourType RefEntityTypeproperty, you will need to use some sort of surrogate forTypethat can be serialized, for instance a string.Thus the following version of
RefDomaincan be serialized via the data contract serializer:Notes:
Deserializing a type supplied over the wire will make your application vulnerable to attack gadget deserialization attacks, in which an attacker tricks your app into constructing a type that effects an attack when constructed, deserialized or disposed. This is a known vulnerability with Json.NET's
TypeNameHandling. See for details:If your app ever constructs an instance of your
RefEntityType, you app may become vulnerable to such attacks. To prevent this, you could check the deserialized type against a whitelist of allowed types.In your question, you ask why the partially public properties of
RefDomainare serialized when it is serialized as a member of some other root objectRefEntity. There is not enough information in your question to explain why this is happening. Perhaps the endpoint where theRefEntityis serialized is using a has subclassedRefDomain, or uses a serialization surrogate, or has setDataContractSerializerSettings.SerializeReadOnlyTypes = true.But regardless of why partially public properties
RefDomainproperties are serialized when insideRefEntity, if you want those properties serialized in all contexts, it is correct and sufficient to markRefDomainwith[DataContract]and the properties with[DataMember]Demo fiddle #2 here.