Adding IPrincipal to the list of known types in WCF

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 :-).

Comments