35

How to use DataContract with inheritance? Will code below work?

[DataContract]
public class ConsoleData
{
    [DataMember]
    public String Description { get; set; }

}

[DataContract]
public class SomeData : ConsoleData
{

    [DataMember]
    public int Volume { get; set; }
    ......
Oleg Vazhnev
  • 23,239
  • 54
  • 171
  • 305

2 Answers2

49

Yes, that would work.

The DataContractAttribute has Inherited set to false, so it is necessary to apply the attribute to both the child class and the parent class (as you have done in the question).


You would need to use the KnownType attribute if you want to use your data contracts with polymorphism.

For example

 [ServiceContract]
 interface MyWcfContract
 {
       [OperationContract]
       HandleData(ConsoleData contractData);
 }

If you invoked the method like so:

 SomeData someData = new SomeData { Description = "Test", Volume = 30 };
 // The method is expecting a ConsoleData instance, 
 // I'm passing a SomeData instance instead
 myWcfProxy.HandleData(someData);

Then the deserializer on the service end will not know that it's an instance of SomeData, just an instance of ConsoleData which it was expecting. The way to fix this is to register the SomeData class as a known type of the ConsoleData.

[DataContract]
[KnownType(typeof(SomeData))]
public class ConsoleData
{
    [DataMember]
    public String Description { get; set; }

}

[DataContract]
public class SomeData : ConsoleData
{

    [DataMember]
    public int Volume { get; set; }
    ......
Andrew Shepherd
  • 44,254
  • 30
  • 139
  • 205
  • @Andrew. I am fightening with these subjects a long time. Is it possible to have in `[OperationContract] HandleData(Base base);` and send from SoapUI some drieved objects from `Base` ? And then if c# will be aware of fact that on `base` it is hold instance of some subclass - so it invoke proper methods also (polymorphism and so on) –  Apr 06 '17 at 08:39
  • There was a minor syntax error in [KnownType(typeof(SomeData))] , thanks for the helpful post. – Shanjee Jan 09 '18 at 09:33
  • @Shanjee Thanks, I've added the extra bracket. It took seven years for someone to notice :-) – Andrew Shepherd Jan 09 '18 at 10:53
2

You'll need to use the KnownType attribute if you are using the XmlSerializerFormat for your ServiceContract:

[DataContract]
public class ConsoleData
{
    [DataMember]
    public String Description { get; set; }
}

[DataContract, KnownType(typeof(ConsoleData))]
public class SomeData : ConsoleData
{
    [DataMember]
    public int Volume { get; set; }
}
M.Babcock
  • 18,753
  • 6
  • 54
  • 84
  • what will not work without `KnownType`? I've tried code as I wrote in description and it seems to work – Oleg Vazhnev Dec 18 '11 at 21:59
  • 2
    I question this. It makes sense to put KnownType(typeof(SomeData)) on the base class (ConsoleData), allowing you to pass a child instance to a method expecting a base instance. But I don't think you need to put it on the child instance. – Andrew Shepherd Dec 18 '11 at 22:02
  • @javapowered: Just take care if you decide not to use the KnownType attribute because there are special cases where it is required. One such example is if you were to expose SomeData as a property of yet another DataContract. – M.Babcock Dec 18 '11 at 22:03
  • @AndrewShepherd: In the testing I did on it a couple weeks ago it didn't seem to matter whether the attribute was put on the parent or child (it worked either way). – M.Babcock Dec 18 '11 at 22:04
  • 1
    @M.Babcock - Sorry for badgering on here: In the case I'm trying, you do not need the KnownType attribute. Could you provide an example usage where the KnownType attribute is actually required? (ie a piece of code which would not work without the attribute) – Andrew Shepherd Dec 18 '11 at 22:08
  • @AndrewShepherd: I reviewed my research notes and it looks like it was only required when using the XmlSerializerFormat attribute on my Service Contract. – M.Babcock Dec 18 '11 at 22:11
  • @M.Babcock. I am fightening with these subjects a long time. Is it possible to have in [OperationContract] HandleData(Base base); and send from SoapUI some derieved objects from `Base` ? And then if c# will be aware of fact that on `base` it is hold instance of some subclass - so it invoke proper methods also (polymorphism and so on) –  Apr 06 '17 at 08:39