WCF列表<string>序列化/反序列化错误

我有以下ServiceContract和DataContract类:

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

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

当Response.Data字典的值类型为int,string,double或任何其他“简单”基元类型时,WCF可以成功序列化该对象。 但是,当Response.Data字典的值为List <string>类型时,客户端在接收到数据并尝试反序列化时抛出以下异常:

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 <string,object>:服务器需要向客户端发送一个'dynamic'数据字典,可以是int,List,DataTime等。它将通过使用Dictionary来帮助解决这个问题,但它也丢失了原始的类型信息。 例如,客户端需要List并执行一些数据绑定来显示集合,因此在这种情况下List.ToString()将不会有帮助。


我认为默认情况下System.Object不是Serializable 。 你需要发送额外的信息,但它仍然不是最佳实践,我建议在使用你的字典之前定义一个单独的类型。

请参阅以下内容:

WCF服务返回一个字典数组

WCF System.Object序列化

在WCF中序列化IDictionary


请记住,您的数据协定被序列化为字符串,因此您传递的任何对象都必须是可序列化的(该object不是)。

问题在于你在面向服务的上下文中使用面向对象的模式 - 期望你在字典值中传递的所有东西都是多态object 。 我回答了一个有类似“气味”的问题:https://stackoverflow.com/a/19445875/2382536。

这个问题是由于WCF非常擅长抽象化服务的底层渠道,所以您很想忘记您现在正在使用“面向服务”的上下文( KnownTypes是一种黑客 - 给出了面向对象的错觉在电线上)。 数据合同构成了您的服务的“公共”API的一部分,因此必须明确表示您的服务所暴露的数据。 拥有返回“动态”数据的数据结构违反了这一重要规则。

客户端需要知道它返回的数据,所以如果你想实现一个“动态”响应,你应该为响应的变化实现(比如说)不同的方法/端点/服务。 在您的服务中,没有理由不能使用多态来简化代码 - 但这不应该泄漏到公共服务/数据合约中。


感谢大家的投入。 我设法通过配置WCF使用NetDataContractSerializer作为序列化程序(默认为DataContractSerializer)来解决问题。 NetDataContractSerializer在序列化时会包含更多的CLR类型信息,尽管它具有性能优势(大约是序列化时间的两倍)。

链接地址: http://www.djcxy.com/p/16703.html

上一篇: WCF List<string > serialization/deserialization error

下一篇: How to style textfield recently results