询问者
反序列化问题: 模型更新后无法反序列化(格式化程序尝试对消息反序列化时引发异常)

问题
-
错误提示: 格式化程序尝试对消息反序列化时引发异常. "info"并非所需参数.所需参数为"_x003C_transfer_trade_no_x003E_k_BackingFiled".. (新手不能发图片...)
接口请求:
[OperationContract]
Return<object> AddDistributeInfo(string outtradeno, WapPayDistributeView info);
更新前的模型(info):
[Serializable]
public class WapPayDistributeView
{
[DataMember]
public string out_bill_no { get; set; }
[DataMember]
public string royalty_email { get; set; }
[DataMember]
public string royalty_amount { get; set; }
[DataMember]
public string royalty_note { get; set; }
[DataMember]
public string storeSysNo { get; set; }
[DataMember]
public string order_amount { get; set; }
}
更新后的模型(info):
[Serializable]
public class WapPayDistributeView
{
[DataMember]
public string out_bill_no { get; set; }
[DataMember]
public string royalty_email { get; set; }
[DataMember]
public string royalty_amount { get; set; }
[DataMember]
public string royalty_note { get; set; }
[DataMember]
public string storeSysNo { get; set; }
[DataMember]
public string order_amount { get; set; }
[DataMember]
public string distribute_trade_no { get; set; }
}
问题描述:
(服务器:两台带负载均衡,WCF是.Net FrameWork 4.0版本,请求端是.Net FrameWork 4.5版本)
这个接口(Adddistribute方法)一直是可以用的, 后来在接口的参数(WapPayDistributeView类)info里加了一个(string)distribute_trade_no,
唯一的变化就是新增的这个字段.结果导致接口请求反序列化报错,而且是偶尔报错.当时把模型库dll重新更新了,以排除模型版本问题,但还是偶尔出现接口调用失败.
错误提示: "info"并非所需参数,所需参数为"_x003C_transfer_trade_no_x003E_k_BackingFiled"..
1是两边的系列化和反序列化对应不上吗? 但是用的都是同一个模型类啊.
2这里提示的info是不是默认的DataContract序列化器序列化的,而x003C_transfer_trade_no_x003E_k_BackingFiled 是由 Serilizirale特性 指示序列化的? 但是以前的模型类也都是这么写,怎么会偶尔出现调用失败的情况?
3会不会是请求端和服务端口.Net FrameWork 的版本不一样, 使序列化和反序列化的机制也不一样?但是这是偶然发生的调用失败.如果序列化问题会一直报错吧
昨天看了一整天还是没找到原因.... 其实我怀疑只是版本更新问题,但是负责发布的经理很确定版本是对的. 后来只能还原这个类了. 找不到原因很难受.. 有劳大师们解答一下...不胜感
全部回复
-
Hi JuliusKingsley,
根据你的描述,这种错误是偶尔性地发生,我认为客户端和服务端对于数据协定类应该是一致地。否则不可能在某些情况下正常工作。在我看来,不同版本的.netframework不会导致这个问题。默认的序列化器的实现都是基于.netframework4.0的。这种错误应该是其他问题的引起地,比如创建通道的绑定设置,MaxReceivedMessageSize, MaxStringContentLength。 我建议你提供更过关于错误的细节。比如,一般在什么情况下会出现这种错误?
另外,没必要对Serializable的类的成员使用Datamember特性。它们已经被显式地标记为序列化。DataMember和DataContract一起使用是为了更好的控制序列化字段(名字空间,序列化字段的名字)。我建议你使用DataContract来表明复杂数据类型的序列化格式。这里是官方的描述。
With [Serializable], all fields become part of the data contract (unless they are marked with [NonSerialized]). With [DataContract], only members marked with [DataMember] are included. Note that if a type has both [DataContract] and [Serializable] attributes on it, it will use the [DataContract] mapping
https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/data-transfer-and-serialization
期待你的回复。
Best Regards
Abraham -
Hi Abraham Qian,
很感谢你的回复. 这里提供更详细的错误信息 :
https://social.msdn.microsoft.com/Forums/getfile/1304718
(报错发生在请求端)
还有终结点的配置信息:(请求端)
<bindings> <basicHttpBinding> <binding name="ServiceForMallBasicHttpBinding" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" maxBufferSize="2097152" maxReceivedMessageSize="2097152" useDefaultWebProxy="false"> <readerQuotas maxDepth="2097152" maxStringContentLength="2097152" maxArrayLength="2097152" maxBytesPerRead="2097152" maxNameTableCharCount="2097152" /> <security mode="None"> <transport clientCredentialType="None" proxyCredentialType="None" realm=""> <!--<extendedProtectionPolicy policyEnforcement="Never" />--> </transport> <message clientCredentialType="UserName" algorithmSuite="Default" /> </security> </binding> <binding name="WebServiceSoap"> <security mode="Transport" /> </binding> <binding name="WebServiceSoap1" /> </basicHttpBinding> <netTcpBinding> <binding name="ServiceForO2ONetTcpBinding" closeTimeout="00:00:10" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" maxBufferSize="209715200" maxReceivedMessageSize="209715200"> <readerQuotas maxDepth="64" maxStringContentLength="209715200" maxArrayLength="1638400" maxBytesPerRead="209715200" maxNameTableCharCount="209715200" /> <security mode="None" /> </binding> </netTcpBinding> </bindings> <client>
<endpoint address="http://localhost:6996/Alipay/AlipayService.svc" binding="basicHttpBinding" bindingConfiguration="ServiceForMallBasicHttpBinding" contract="com.zh.kj.MallWCF.Interfaces.Alipay.ServiceContract.IAlipayService" name="BasicHttpBinding_ICustomerService" /> </client>
还有终结点的配置信息:(服务端)
<bindings> <basicHttpBinding> <binding name="ServiceForMallBasicHttpBinding" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" useDefaultWebProxy="false"> <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="1024000" maxNameTableCharCount="1024000" /> <security mode="None" /> </binding> </basicHttpBinding> </bindings> <services> <service behaviorConfiguration="ServiceForMallhavior" name="com.zh.kj.MallWCF.Service.Alipay.AlipayService"> <endpoint binding="basicHttpBinding" bindingConfiguration="ServiceForMallBasicHttpBinding" contract="com.zh.kj.MallWCF.Interfaces.Alipay.ServiceContract.IAlipayService"></endpoint> </service> </services>
*************** 问题出现的背景:
WapPayDistributeView 类中新增字段 (string)distribute_trade_no , 更新请求端和服务端dll(未重启), 偶尔会发生请求报反序列化错误,原来的WCF接口代码完全没变,只是在传入模型中多了一个字段 .
现在无法重现这个仅在生产环境上出现的问题了....... T_T
*************************************************
你的回复对我很有帮助,
再次表示感谢!
Best Regards
Julius
- 已编辑 JuliusKingsley 2018年8月15日 0:54