意外类型 - 序列化异常

Posted

技术标签:

【中文标题】意外类型 - 序列化异常【英文标题】:Unexpected Type - Serialization Exception 【发布时间】:2011-09-03 10:19:42 【问题描述】:

我有 WCF 服务。

正常操作会看到服务器执行一些处理,通过回调将填充的 XactTaskIn 对象返回给客户端。我有这个工作正常。

我的问题是,当我尝试将 returnData 变量设置为填充的 XactException 并尝试通过回调将 XactTaskIn 发送回客户端时,我会抛出以下异常。

异常 - “类型 'XactException' 与 数据合同名称 'XactException:http://schemas.datacontract.org/2004/07/' 预计不会。考虑使用一个 DataContractResolver 或添加任何类型 不知道静态的列表 已知类型 - 例如,通过使用 KnownTypeAttribute 属性或通过 将它们添加到已知类型列表中 传递给 DataContractSerializer。” (System.Runtime.Serialization.SerializationException) 异常 消息=“键入'XactException' 数据合同名称 'XactException:http://schemas.datacontract.org/2004/07/' 预计不会。考虑使用一个 DataContractResolver 或添加任何类型 不知道静态的列表 已知类型 - 例如,通过使用 KnownTypeAttribute 属性或通过 将它们添加到已知类型列表中 传递给 DataContractSerializer。", 异常类型 = "System.Runtime.Serialization.SerializationException"

这里是 XactTaskIn 类

[DataContract]
public class XactTaskIn

    [DataMember]
    public DateTime timeOut;
    [DataMember]
    public DateTime timeIn;
    [DataMember]
    public string name;
    [DataMember]
    public string responseTo;
    [DataMember]
    public String moduleFromName;
    [DataMember]
    public String moduleFromType;
    [DataMember]
    public String methodFromName;
    [DataMember]
    public object[] originalInputs;
    [DataMember]
    public String returnMethodToCall;
    [DataMember]
    public String returnModuleToCall;
    [DataMember]
    public object returnData;

    public XactTaskIn(DateTime timeOut, DateTime timeIn, string name, string responseTo, String moduleFromName, String moduleFromType, String methodFromName, object[] originalInputs, String returnMethodToCall, String returnModuleToCall, object returnData)
    
        this.timeOut = timeOut;
        this.timeIn = timeIn;
        this.name = name;
        this.responseTo = responseTo;
        this.moduleFromName = moduleFromName;
        this.moduleFromType = moduleFromType;
        this.methodFromName = methodFromName;
        this.originalInputs = originalInputs;
        this.returnMethodToCall = returnMethodToCall;
        this.returnModuleToCall = returnModuleToCall;
        this.returnData = returnData;
    

这是 XactException 类:

[DataContract]    
public class XactException

    [DataMember]
    string message;

    public XactException(string message)
    
        this.message = message;
        // Add implementation.
    

更新:

好的,丹尼尔的评论帮助了我。

现在看起来服务器正在向客户端发送回调,但客户端正在抛出以下异常。

捕获:“格式化程序在尝试反序列化时抛出异常 消息:有一个错误,而 试图反序列化参数 http://tempuri.org/:taskIn。这 InnerException 消息是“错误 第 1 行位置 960. 元素 'http://schemas.datacontract.org/2004/07/:returnData' 包含来自映射到的类型的数据 名字 'http://schemas.datacontract.org/2004/07/:XactException'。 解串器不知道 映射到此名称的任何类型。 考虑使用 DataContractResolver 或者添加对应的类型 'XactException' 到已知列表 类型 - 例如,通过使用 KnownTypeAttribute 属性或由 将其添加到已知类型列表中 传递给 DataContractSerializer。'。 请参阅 InnerException 了解更多信息 细节。” (System.ServiceModel.Dispatcher.NetDispatcherFaultException) 异常 Message = "格式化程序抛出了一个 尝试反序列化时出现异常 消息:有一个错误,而 试图反序列化参数 http://tempuri.org/:taskIn。这 InnerException 消息是“错误 第 1 行位置 960. 元素 'http://schemas.datacontract.org/2004/07/:returnData' 包含来自映射到的类型的数据 名字 'http://schemas.datacontract.org/2004/07/:XactException'。 解串器不知道 映射到此名称的任何类型。 考虑使用 DataContractResolver 或者添加对应的类型 'XactException' 到已知列表 类型 - 例如,通过使用 KnownTypeAttribute 属性或由 将其添加到已知类型列表中 传递给 DataContractSerializer。'。 请参阅 InnerException 了解更多信息 详细信息。”,异常类型 = "System.ServiceModel.Dispatcher.NetDispatcherFaultException"

【问题讨论】:

尝试使用KnownTypeAttribute,如异常中所述。 @Daniel - 我应该把属性放在哪里? @user589195:我想在 XactException 类。 我在类的开头尝试了这个 [KnownType(typeof(object))] 如果你使用[KnownType(typeof(XactException ))]呢? 【参考方案1】:

在你的课堂上

    [DataContract]
    public class XactTaskIn

你有返回对象的属性:

        [DataMember]
        public object[] originalInputs;

        [DataMember]
        public object returnData;

WCF 需要提前知道其中可能存在哪些类型,以便它可以(通过 WSDL)告诉客户端所有类型是什么。对于任何/所有非“本机”类型(任何非 int、字符串、DateTime 等),您需要为可能在这些对象属性中传回的每种可能类型添加 [KnownType] 属性,如下所示:

    [KnownType(typeof(XactException))]
    [KnownType(typeof(...))]
    [KnownType(typeof(...))]
    [DataContract]
    public class XactTaskIn

这样,当 WCF 为服务构建 WSDL 时,它会知道将 XactException 添加到数据类型列表中,并且序列化程序也会知道查找这些类。


旁注;如果您的客户端是使用 SrvUtil、Service Reference 构建的,或者以某种方式从 WSDL 生成的,则需要在添加 [KnownType] 属性后重新构建客户端!

【讨论】:

太棒了,非常感谢,帮助我理解它,而不仅仅是给我答案:) 我还有其他问题,我有一个公共字段,但只有一个 get,在我看到列表中的下一个错误之前需要一个集合【参考方案2】:

您的客户期待 XactTaskIn 而不是 XactException。

您需要更改您的 XactTaskIn 才能将异常对象传递回您的客户端。

删除您的异常数据合同并将 XactException 类型作为数据成员添加到您的 XactTaskIn 类中

【讨论】:

嗨,Ken 感谢您的回答 - 我想我正在尝试按照您的建议进行操作。我不是要向客户端发送 XactException,而是要发送一个 XactTaskIn 对象,它的 returnData 数据成员包含一个 XactException 对象。【参考方案3】:

当数据发生变化时会发生序列化异常,例如将字段名称从awesomeString 更改为awesomeSTring 会导致序列化中断。原因是新数据无法再根据旧数据进行验证。解决此问题的方法是使用服务器/客户端所期望的旧版本。

【讨论】:

以上是关于意外类型 - 序列化异常的主要内容,如果未能解决你的问题,请参考以下文章

意外的子类型:MyNamespace.MyInheritedClass

反序列化包含简单引用实体的xml文件时出现异常

Protobuf 反序列化异常

深度盘点:时序预测之异常检测算法综述

protobuf-net 中通用集合的序列化

解析 API 响应时遇到意外字符