1

I want to inherit from a class which is located in a WCF Service. The Inheritance works fine (I see the properties of the base class in my child class), my problem occurs when I try to call a method from the service and pass the childtype as a parameter and not the basetype.

Base class in WCF Service (Pet):

[ServiceContract]
public interface IService
{
    [OperationContract]
    void BringPet(Pet pet);

    [OperationContract]
    void TakePet(Pet pet);

    [OperationContract]
    List<Pet> GetAllPets();
}

[DataContract]
public class Pet
{
    private string _name;
    private string _color;

    [DataMember]
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    [DataMember]
    public string Color
    {
        get { return _color; }
        set { _color = value; }
    }
}

Class on the client (Dog inherits from Pet):

[DataContract()]
class Dog : PetService.Pet
{
    [DataMember()]
    public bool HasPedigree { get; set; }
    [DataMember()]
    public string Race { get; set; }
}

When I try calling something like this:

        Dog dog = new Dog()
        {
            Color = "Black",
            Name = "Pluto",
            HasPedigree = true,
            Race = "Travolta"
        };

        _client.BringPet(dog);

I get a CommunicationException which says that the type Dog is not expected by the method BringPet(Pet pet). I would solve this problem by setting the KnownType attributes on the service side, but because my service must not know the type Dog I can't set the KnownType or ServiceKnownType attributes.

Can someone help me out?

danjov
  • 63
  • 1
  • 6

2 Answers2

4

If you want to have inherited classes that get returned instead of the ones defined in your service contract, you need to make this fact known to WCF by means of the ServiceKnownType attribute:

[ServiceContract]
[ServiceKnownType(typeof(Dog))]
public interface IService
{
    [OperationContract]
    void BringPet(Pet pet);

    [OperationContract]
    void TakePet(Pet pet);

    [OperationContract]
    List<Pet> GetAllPets();
}

This basically tells the WCF service to also allow classes of type Dog to be used in your service.

Or you can decorate your data contract with the KnownType attribute:

[DataContract]
[KnownType(typeof(Dog))]
public class Pet
{
.....
}

to associate your data contract type with additional types that could be used in its place.

One way or the other: you have to make your extra type known to the WCF runtime - WCF cannot figure out that fact by just checking .NET type inheritance.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • Thank you for your answer. I would do it exactly how you explained it but I can't, because the WCF service must not know the extra type. I'll try the generic solution. – danjov Sep 22 '10 at 12:58
  • @marc_s can look here ? http://stackoverflow.com/questions/42294978/lack-of-sent-field-from-sublcass-in-wcf-trying-to-gain-polymorphism?noredirect=1#comment71750175_42294978 I have very similar problem –  Feb 17 '17 at 13:47
2

I think this is very similar to this question: Service - client interface, architecture advice

As you will see, there is no really easy way to do this without making your service operation more generic.

Community
  • 1
  • 1
stombeur
  • 2,704
  • 22
  • 45
  • Hi, @stombeur, maybe can you look here ?http://stackoverflow.com/questions/42294978/lack-of-sent-field-from-sublcass-in-wcf-trying-to-gain-polymorphism?noredirect=1#comment71750175_42294978 –  Feb 17 '17 at 13:48