MrEff
MrEff

Reputation: 89

WCF Polymorphic Parameter

I have a WCF service that exposes a function:

Public Function FeedAnimal(ByVal animal As Animal) As Animal Implements IFarm.FeedAnimal
    animal.Feed()
    Return animal;
End Function

However Animal is an abstract class with many derived types, each with their own properties. When I make a request in SOAPUI with the properties that would indicate a Cow, however, I get an error that I cannot create an abstract class. How do I get WCF to deserialize the parameter into its actual type? Let's assume they are all distinguishable by their differently named properties.

I have already tried adding the KnownType attribute everywhere it will go, to no avail. Doing that allowed me to return derived types, but not accept them as parameters.

If what I'm trying to do is totally crazy, please tell me the next closest thing

Edited; I would be satisfied if I can make it fall back to the XmlSerializer for this function only, which used to work in a previous version

[ServiceContract(Namespace:=Constants.SERVICE_NAMESPACE)]
[ServiceKnownType(GetType(Cow))]
Public Interface IFarm
    [OperationContract()]
    [ServiceKnownType(GetType(Cow))]
    [Validation(CheckAssertions:=False, SchemaValidation:=True)]
    Function FeedAnimal(ByVal animal As Animal) _
        As Animal
End Interface

And the classes

[KnownType(GetType(Cow))]
Public MustInherit Class Animal
    Public weight As Integer
End Class

Public Class Cow
    Inherits Animal
    Public mooPower As Double
End Class

And the request:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:v3="mycomapnyaddresss" xmlns:foo="animalnamespace">
   <soap:Header/>
   <soap:Body>
  <v3:FeedAnimal>
     <!--Optional:-->
     <v3:animal>
        <!--Optional:-->
        <foo:weight>100</foo:weight>
        <foo:mooPower>10.0</foo:mooPower>
     </v3:animal>
  </v3:FeedAnimal>

Upvotes: 0

Views: 193

Answers (2)

Fede
Fede

Reputation: 44038

You have to add the KnownType attribute to the contract:

<DataContract(), KnownType(GetType(Cow)), KnownType(GetType(Dog))> _
Public Class Animal
   ...
End Class

Upvotes: 1

TheNextman
TheNextman

Reputation: 12566

Have you tried the ServiceKnownType attribute?

There is a blog post here MSDN that explains it quite well.

ServiceKnownType goes on the actual service interface itself...

Upvotes: 1

Related Questions