Ошибка сериализации/десериализации списка WCF

у меня есть следующие классы ServiceContract и DataContract:

[ServiceContract] 
public interface IWcfService 
{ 
    [OperationContract] 
    Response GetData(); 
} 

[DataContract]
public class Response 
{ 
    [DataMember] 
    public Dictionary<string, object> Data { get; set; } 
} 

когда значение ответа.Словарь данных имеет тип int, string, double или любые другие "простые" примитивные типы, WCF может успешно сериализовать объект. Но когда значение ответа.Словарь данных имеет тип List, клиент бросил следующее исключение, когда он получил данные и попытался десериализовать его:

Message=The formatter threw an exception while trying to deserialize the message: 
There was an error while trying to deserialize parameter http://tempuri.org/:GetDataResult. 
The InnerException message was 'Error in line 1 position 990. 
    Element 'http://schemas.microsoft.com/2003/10/Serialization/Arrays:Value' contains data from a type 
    that maps to the name 'http://schemas.microsoft.com/2003/10/Serialization/Arrays:ArrayOfstring'. 
    The deserializer has no knowledge of any type that maps to this name. 
    Consider using a DataContractResolver or add the type corresponding to 'ArrayOfstring' 
    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.'.

Я также попытался добавить атрибут KnownType в ServiceContract и DataContract, как показано ниже:

[ServiceContract] 
[ServiceKnownType(typeof(List<string>))] 
[ServiceKnownType(typeof(Dictionary<string, string>))] 
[ServiceKnownType(typeof(Dictionary<string, List<string>>))] 
public interface IWcfService 
{ 
    [OperationContract] 
    [ServiceKnownType(typeof(List<string>))] 
    [ServiceKnownType(typeof(Dictionary<string, string>))] 
    [ServiceKnownType(typeof(Dictionary<string, List<string>>))] 
    Response GetData(); 
} 

[DataContract] 
[ServiceKnownType(typeof(List<string>))] 
[ServiceKnownType(typeof(Dictionary<string, string>))] 
[ServiceKnownType(typeof(Dictionary<string, List<string>>))] 
[KnownType(typeof(List<string>))] 
[KnownType(typeof(Dictionary<string, string>))] 
[KnownType(typeof(Dictionary<string, List<string>>))] 
public class Response 
{ 
    [DataMember] 
    public Dictionary<string, object> Data { get; set; } 
} 

но ничего из этого не помогло. У кого-нибудь есть идеи?

Обновлено

данные будут выглядеть так:

Data = new new DIctionary<string, object> 
       { 
           {"_id", 12344}, 
           {"names", new List<string>{ "John", "Peter", "Jack"}}, 
           {"time", DateTime.Now} 
       }

причина, по которой мы использовали Dictionary: Сервер должен отправить клиенту словарь "динамических" данных, который может быть int,List, DataTime и т. д. Это поможет повернуть эту проблему с помощью словаря, но также потеряет исходный тип информация. Например, клиенту требуется список и выполнить привязку данных для отображения коллекции so List.ToString () не будет полезен в этом случае.

3 ответов


Я думаю по умолчанию System.Object не Serializable. Вам нужно отправить дополнительную информацию, но это все равно не лучшая практика, я рекомендую определить отдельный тип перед использованием словаря.

см. ниже:

служба WCF возвращает массив словаря

система WCF.Сериализация Объектов

сериализация IDictionary в WCF


имейте в виду, что ваш контракт данных сериализуется в строки по проводу, поэтому любой объект, который вы передаете, должен быть сериализуемым (который object нет).

проблема в том, что вы используете объектно-ориентированные шаблоны в контексте, ориентированном на службу, ожидая, что все, что вы передаете в своем словарном значении, будет полиморфным object. Я ответил на вопрос, который имел похожие "запахи" Здесь:https://stackoverflow.com/a/19445875/2382536.

проблема связана с тем, что WCF настолько хорош в абстрагировании основного канала вашей службы, что вы склонны забывать, что теперь вы работаете в контексте, ориентированном на службу (KnownTypes - это хак, дающий иллюзию OO над проводом). Контракт данных является частью "публичного" API для вашей службы и как таковой должен быть четким явным представлением данных, предоставляемых вашей службой. Наличие структуры данных, возвращающей "динамические" данные нарушает это важное правило.

клиент должен знать, какие данные он возвращает, поэтому, если вы хотите реализовать "динамический" ответ, вы должны реализовать (скажем) различные методы/конечные точки/службы для вариаций ответа. В вашей службе нет причин, по которым вы не можете использовать полиморфизм для упрощения кода, но это не должно просачиваться в контракты на государственную службу/данные.


Спасибо за вклад каждого. Мне удалось решить проблему, настроив WCF для использования NetDataContractSerializer в качестве сериализатора (по умолчанию это DataContractSerializer). NetDataContractSerializer будет включать больше информации о типе среды CLR при сериализации, хотя он имеет хит производительности (примерно вдвое больше времени сериализации).