views:

59

answers:

2

I have various classes which I want to expose as Complex Types in WCF, so I add [DataContract] and [DataMember] attributes as necessary on those types and properties.

However if I want to have them inherit from an abstract base class (for example Person inherits from abstract EntityBase), I get an error that the type "cannot inherit from a type that is not marked with DataContractAttribute or SerializableAttribute".

The problem is, if I add [DataContract] attribute to the base class, then that base class is exposed to the client via the WSDL. Not a huge deal I guess, but I would prefer my client doesn't know about my internal implementation.

If I add the [Serializable] attribute to the base class, then it seemed to work at first (it could be serialized but EntityBase was not referenced in the WSDL), but now if I add any properties to EntityBase then it will also complain that its properties are not serializable. (For example I add an ICollection then I get an error that RuleViolation is not serializable).

Unfortunately there seems to be no analogue to [IgnoreDataMember] for a [Serializable] type ([NonSerialized applies only to fields, not properties).

So basically I want to declare this base type but don't need any of its members to be serialized; is there any way to set this up in WCF so the client doesn't see this base type?

A: 

I think you have to use the KnownType attribute. For instance see http://stackoverflow.com/questions/3010488/wcf-issues-with-knowntype-for-dictionary

[EDIT] A more complete discussion of this problem and its solution can be found here: http://stackoverflow.com/questions/1376495/wcf-interfaces-generics-and-serviceknowntype

Peladao
Thanks Peladao, I did already try using KnownType (on both the base class and derived class) but it would still throw the error if the class itself weren't marked with one of the two serialization attributes.
Toby J
A: 

Did you try not makring your entities with DataContract and DataMember at all (so that default serialization is used) and mark base class properties with IgnoreDataMember?

You always have several choices and I'm affraid you will not like any of them.

  • Create set of DTO objects and convert entities to DTO. Generally best practice if you want to hide your inner implementation.
  • Create suroggate class (implement IDataContractSuroggate) for each entity so that you have control over serialization - I'm not sure if this avoids the problem.
  • Upgrade to .NET 4.0 and use EF with POCO classes (no EntityBase as parent)

Best regards, Ladislav

Ladislav Mrnka
Thanks for the suggestions Ladislav. I should have mentioned that I am already using EF4/POCO, EntityBase is my own, not part of EF. I did not try using "default" serialization but I'm just really not comfortable with its "opt out" type model. You're right about the possibility to use DTO but at this point the "problem" isn't bad enough to be worth the trouble.
Toby J