views:

518

answers:

2

I'm writing a WCF service to replace a current web service, and I'm having trouble with one of the legacy complex types that I need to return.

Unfortunately I can't touch any of the code but looking at them all the classes are Serializable and the current web service is using it with no problem.

Whenever my client calls the WCF service it gets a Communication Exception and when I turned on tracing for WCF here's the serialization error I found:

Type 'Common.Permission.ApplicationGroup' with data contract name 'ApplicationGroup:http://schemas.datacontract.org/2004/07/Common.Permission' 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.

The type I want to return is ApplicationPrincipal, but it seems to be falling over at a child type. Here's how these classes look:

The type I want to return:

[Serializable]
[TypeConverter(typeof(ExpandableObjectConverter))]
public class ApplicationPrincipal : 
    IPrincipal, ISupportInitialize, IDeserializationCallback, IFormattable
{
    private ApplicationIdentity m_identity;
    private ApplicationGroupCollection m_groups;
    private ConditionDictionary m_roleConditions;

and here's ApplicationGroupCollection:

[Serializable]
public class ApplicationGroupCollection : 
    IList, IEnumerable, IFormattable, ISupportInitialize, 
    IDeserializationCallback, ICloneable, ICustomTypeDescriptor
{
    /// <summary>
    /// Occurs when a value is being changed in the collection.
    /// </summary>
    [field:NonSerialized]
    public event CollectionChangeEventHandler CollectionChanging;

    /// <summary>
    /// Occurs when a value has been changed in the collection.
    /// </summary>
    [field:NonSerialized]
    public event CollectionChangeEventHandler CollectionChanged;

and finally, ApplicationGroup:

[Serializable]
[TypeConverter(typeof(ExpandableObjectConverter))]
public class ApplicationGroup : 
    ICloneable, ISupportInitialize, IDeserializationCallback, IFormattable
{
    private int m_groupID;
    private string m_groupName;
    private string m_groupDesc;
    private ConditionDictionary m_roleConditions;

Any suggestions as to why WCF is not able to serialize ApplicationGroup?

+2  A: 

Try adding these to the top of your DataContract:

[KnownType(typeof(ApplicationGroupCollection))]
[KnownType(typeof(ApplicationGroup))]

[Edit] Without testing I cannot tell you if this will do the trick - I am wondering if the DataContractSerializer will be able to serialize your legacy types as the DataContractSerializer requires that types "opt-in" with attributes on the type and all members that need serialization.

[Edit] Here is the reason for the second set of errors you are seeing. If you are returning a custom type from a service then the client needs to have a copy of that type so that it can deserialize the message. This means that you will need to provide a copy of the assemblies that contain the legacy types to the client for the client to reference.

Andrew Hare
+1  A: 

I think Andrew is correct.

Also, see Chapter 3 of "Programming WCF Services" by Juval Lowy. It contains extensive information about DataContracts and I'm pretty sure it covers exactly what you're asking here.

Terry Donaghe
thanks for the pointer, I've just got my hands on a copy of Juval Lowy's book (2nd edition even!) on sarfaribooksonline, will have a look at chapter 3 and get more familiar with datacontract requirements in WCF
theburningmonk
It's by far the best WCF reference I've seen.
Terry Donaghe