Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF DataContract Exclude DataMembers From Being Serialized In Derived Classes

Tags:

wcf

I have a base class with DataMember properties in it. I also have a derived class with DataMember properties in it. In my WCF project I am returning the derived class. Is there a way for me to prevent a member in my base class from serializing? Here is some sample code:

public class BaseClass
{
    public string ShortDescription {get;set;}
    public string LongDescription {get;set;}
}

public class DerivedClass : BaseClass
{
    public List<Description> Descriptions {get;set;}
}

In this code I want to be able to hide the inherited members ShortDescription and LongDescription because they are now obsolete. Any attempts to do so have been unsuccessful. Here is what I have tried:

public class DerivedClass : BaseClass
{
    [DataMember]
    public List<Description> Descriptions {get;set;}

    // override the base class members
    [IgnoreDataMember]    
    public override string ShortDescription {get;set;}
    [IgnoreDataMember]
    public override string LongDescription {get;set;}
}

and

public class DerivedClass : BaseClass
{
    [DataMember]
    public List<Description> Descriptions {get;set;}

    // shadow the base class members
    [IgnoreDataMember]    
    public new string ShortDescription {get;set;}
    [IgnoreDataMember]
    public new string LongDescription {get;set;}
}

Neither of these approaches have worked. The "DerivedClass" type when output to the WSDL still contains the "Ignored" members of the base class type.

You may wonder why I'm not just changing the base class. This is because I still use the base class in its original form as the previous version of the type for the WSDL to support backwards compatibility for consumers. In this way I can have a v1000 call that returns BaseClass and a V1010 call that returns a DerivedClass. I can add and change functionality to the DerivedClass all I want without the potential for affecting consumers of the v1000 functionality.

like image 935
omatase Avatar asked Aug 26 '10 16:08

omatase


People also ask

Is Datacontract mandatory in WCF?

No, the DataContractAttribute is not required - WCF will infer serialization rules.

What is Datacontract and Datamember in WCF?

A datacontract is a formal agreement between a client and service that abstractly describes the data to be exchanged. In WCF, the most common way of serialization is to make the type with the datacontract attribute and each member as datamember.

Why Datacontract is used in WCF?

It defines the structure and types of data exchanged in service messages. It maps a CLR type to an XML Schema. It defines how data types are serialized and deserialized. Through serialization, you convert an object into a sequence of bytes that can be transmitted over a network.

How do you serialize an object in WCF?

This code constructs an instance of the DataContractSerializer that can be used only to serialize or deserialize instances of the Person class. DataContractSerializer dcs = new DataContractSerializer(typeof(Person)); // This can now be used to serialize/deserialize Person but not PurchaseOrder.


2 Answers

Try adding the [DataContract] attribute to both classes. This will tell the serializer to look at the [DataMember] and [IgnoreDataMember] attributes. Without the class being attributed with [DataContract], all public members are serialized.

[DataContract]
public class BaseClass
{
    [IgnoreDataMember]
    public string ShortDescription {get;set;}

    [IgnoreDataMember]
    public string LongDescription {get;set;}
}

[DataContract]
public class DerivedClass : BaseClass
{
    [DataMember]
    public List<Description> Descriptions {get;set;}
}

Also, it would be even better to add a namespace to your datacontracts by specifying it in the [DataContract(Namespace="...")] attribute. That would break old clients calling your updated service.

like image 148
joelsand Avatar answered Oct 23 '22 13:10

joelsand


Eventually I found a suitable way to handle this task. I don't have the code in front of me so I'm going to wing the syntax. It's a pretty simple solution, but it solves the specific issue I was having.

public class BaseClass
{
    // leave this guy empty
}

public class DerivedClassVersion1 : BaseClass
{
    [DataMember]
    public string ShortDescription {get;set;}

    [DataMember]
    public string LongDescription {get;set;}
}

public class DerivedClassVersion2 : BaseClass
{
    [DataMember]
    public List<Description> Descriptions {get;set;}
}

Badda bing! Pretty simple, but it's what I needed.

like image 31
omatase Avatar answered Oct 23 '22 14:10

omatase