views:

50

answers:

3

Hello

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?

A: 

i think , it's my assumption that You can not override metadata on client and make some changes which service does not know about. and when you call a service from client , service will expect the exact parameter as defind in its contract , otherwise there is no use of Service Contract

saurabh
Thank you for answering my question. I chose the answer from StephaneT because he provides a possible solution for my problem.
Jottiza
A: 

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
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.
Jottiza
A: 

I think this is very similar to this question: http://stackoverflow.com/questions/1907604/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.

StephaneT
Thank you, I'll give it a try.
Jottiza