Итак, проблема. Есть контракт сервиса:
- [ServiceContract]
- public interface IService1
- {
- [OperationContract]
- string GetData(int value);
- [OperationContract]
- CompositeType GetDataUsingDataContract(CompositeType composite);
- }
* This source code was highlighted with Source Code Highlighter.
Описание CompositeType ниже:
- [DataContract]
- public class CompositeType
- {
- [DataMember]
- public string StringValue
- {
- get;
- set;
- }
- [DataMember]
- public Dictionary<string, object> Parameters
- {
- get;
- set;
- }
- }
* This source code was highlighted with Source Code Highlighter.
Все довольно просто.
Создаем простой клиент для этого сервиса и пытаемся передать int[] в нашем словаре параметров CompositeType.Parametes (Dictionary):
- Service1Client client = new Service1Client();
- CompositeType input = new CompositeType();
- input.Parameters= new Dictionary<string, object>();
- input.Parameters.Add("array", new int[] { 1, 2 });
- CompositeType output = client.GetDataUsingDataContract(input);
* This source code was highlighted with Source Code Highlighter.
И при работе получаем такое вот исключение:
There was an error while trying to serialize parameter http://tempuri.org/:composite. The InnerException message was 'Type 'System.Int32[]' with data contract name 'ArrayOfint:http://schemas.microsoft.com/2003/10/Serialization/Arrays' 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.'. Please see InnerException for more details.
В интернете куча таких постов, которые до сих пор висят без ответа. Ни ServiceKnownType, ни KnowType аттрибуты не помогают. Потому что они работают для классов-наследников.
Решение этой проблемы гениально просто.
Добавляем аттрибут [KnownType(typeof(int[]))] или [ServiceKnownType(typeof(int[]))] куда нужно и в DataContract-класс добавляем поле типа System.Object.
(For english readers: solution is pretty smart. Just add to DataContract-class DataMember field of type System.Object. Then use KnownType or ServiceKnownType attributes )
- [DataContract]
- [KnownType(typeof(int[]))]
- public class CompositeType
- {
- [DataMember]
- public object UsedForKnownTypeSerializationObject;
- [DataMember]
- public string StringValue
- {
- get;
- set;
- }
- [DataMember]
- public Dictionary<string, object> Parameters
- {
- get;
- set;
- }
- }
* This source code was highlighted with Source Code Highlighter.
Похожий вопрос тута
All about known types
Data Contract Known Types
No comments:
Post a Comment