WCF has a concept called Known Types, which lets WCF handle subclasses and interface implementations passed to services. Normally you can just whack a KnownTypeAttribute on your DataContract and you’re good to go:
[DataContract] [KnownType(typeof(Manager))] public class Employee { ... }
In the example above, the service will be able to use the Manager
subclass anywhere it expects an Employee
.
This doesn’t help much when you want to use non-DataContract types like IPrincipal
. Trying to pass a GenericPrincipal
to a service operation that expects an IPrincipal
gives you an error message like this (line breaks added for slightly improved legibility):
System.Runtime.Serialization.SerializationException: Type 'System.Security.Principal.GenericPrincipal' with data contract name 'GenericPrincipal:http://schemas.datacontract.org/2004/07/System.Security.Principal' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
One solution is to decorate your service contract with a ServiceKnownTypeAttribute:
[ServiceContract] [ServiceKnownType(typeof(GenericIdentity))] [ServiceKnownType(typeof(GenericPrincipal))] public interface ISomeService { [OperationContract] String DoSomethingWith(IPrincipal principal); }
While I don’t necessarily recommend exposing IPrincipal
through your service, the technique is worth knowing about. Most of the search results I got mentioned KnownTypeAttribute
and not ServiceKnownTypeAttribute
.
Thanks to Steven Cheng who answered this question in his response to this post. Steven also provided a link to Bennie Haelen’s fantastic post on Handling Data Contract Object Hierarchies in WCF, which covers more than you could ever want to know about this stuff :-).