views:

575

answers:

2

Hello there.

I would like to aks you for your help. I have here problem with WCF deserialization of Dictionary where Enum type is used as a key.

I have two data objects:

[DataContract] 
public enum MyEnum : int
{
   [EnumMember]
   Value1 = 0,
   [EnumMember]
   Value2 = 1
}

and

[DataContract]
[KnownType(typeof(MyEnum))] 
public class ReturnData
{
   [DataMember]
   public IDictionary<Enum, string> codes;
}

In fact ReturnData class contains more data members but they are not important for my example.

These data objects are returned by method:

[OperationContract]
public ReturnData Method1()
{
 ReturnData data = new ReturnData();
 data.codes = new Dictionary<Enum, string>();
 data.codes.Add(MyEnum.Value1, "stringA");

 return data;
}

When I call Method1 from client side then next exception is thrown:

The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:Method1Result. The InnerException message was 'Error in line 1 position 522. Element 'http://schemas.microsoft.com/2003/10/Serialization/Arrays:Key' contains data of the 'http://schemas.datacontract.org/2004/07/AMService:MyEnum' data contract. The deserializer has no knowledge of any type that maps to this contract. Add the type corresponding to 'MyEnum' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.'

Any idea how to define ReturnData class to solve this problem?

Note: When I change ReturnData member codes to use as key data type MyEnum instead of Enum public IDictionary<MyEnum, string> codes; then deserialization works correctly and data are transferred from server side to client side without problem.

Thanks for your help.

+2  A: 

At the top of your class add a KnownType attribute.

using System.Runtime.Serialization;

[KnownType(typeof(MyEnum))]
[DataContract]
public class Foo {

}
kime waza
kime waza thanks for your answer. But If you check my class ReturnData again you can see 'KnownType' attribute is already there...
Jason dinAlt
yeah did you add that after i did my answer, i didn't see it before? :) Have you tried regenerating the client proxy with the KnownType attribute in place on the server?
kime waza
A: 

should'nt this line

data.codes = new Dictionary<Enum, string>();

be

data.codes = new Dictionary<MyEnum, string>();
Neil
No.It is not possible to compile: IDictionary<Enum, string> codes = new Dictionary<MyEnum, string>();
Jason dinAlt
how about IDictionary<MyEnum, string> codes = new Dictionary<MyEnum, string>();
Neil
Yes this works. It is written in Note section of my original post. But question is how to make serializable IDictionary<Enum, string> data member.
Jason dinAlt
ah sorry, try placing the [KnownType(typeof(MyEnum))] on the declaration for public enum MyEnum, just a guess
Neil