How To Use Interface as DataContract in WCF

thr0w picture thr0w · Apr 5, 2013 · Viewed 10.1k times · Source

I need invoke webservice operations using standard wsdl, but data objects must be different in client and in the server.

Using interfaces for data objects in a common library, making proxy classes for it in client and in server.

Then, I'm declaring operation contract using the interface, but WCF don't recognize it.

I yet tried use DataContractSerializerBehavior and set knownTypes, no success yet.

Someone can help-me? I've attached a complete solution with more details.

public interface Thing
{
   Guid Id {get;set;}
   String name {get;set;}
   Thing anotherThing {get;set;}
}

[DataContract]
public class ThingAtServer: BsonDocument, Thing // MongoDB persistence
{ 
   [DataMember]
   Guid Id {get;set;}
   //... 
}

[DataContract]
public class ThingAtClient: Thing, INotifyPropertyChanged // WPF bindings
{ 
   [DataMember]
   Guid Id {get;set;}
   //... 
}

[ServiceContract]
public interface MyService
{
  [OperationContract]
  Thing doSomething(Thing input);
}

Click here do see a Sample project on GitHub with TestCases

Answer

Enes picture Enes · Apr 6, 2013

I've created WCF Service with contract:

[OperationContract]
CompositeTypeServer GetDataUsingDataContract( CompositeTypeServer composite );

My CompositeTypeServer looks like this:

[DataContract( Namespace = "http://enes.com/" )]
public class CompositeTypeServer
{
    [DataMember]
    public bool BoolValue { get; set; }

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

Then I've created client project with type CompositeTypeClient:

[DataContract( Namespace = "http://enes.com/" )]
public class CompositeTypeClient
{
    [DataMember]
    public bool BoolValue { get; set; }

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

Then I've added the reference to my service and selected to reuse types. Everything worked like charm. I was able to use CompositeTypeClient on client side.

So the trick was to specify Namespace for DataContract so they would match on both client and service.

[DataContract( Namespace = "http://enes.com/" )]

PS. I can provide full working VS solution on request.