SOAP WebService请求序列化异常:仅前5个属性被填充求助
从你描述的现象——无论调整SOAP请求中属性的顺序,始终只有前5个属性能被正确反序列化赋值,后续属性均为默认值——来看,最可能的原因是WCF DataContractSerializer的反序列化配额限制,或者是未显式指定DataMember的Order属性导致的顺序不匹配问题,下面给你一步步排查和解决的方案:
1. 检查并调整DataContractSerializer的maxItemsInObjectGraph配置
WCF的DataContractSerializer默认有一个对象图中最大项数的限制(默认值是65536),但如果你的服务配置中被意外修改为较小的值(比如5),就会导致反序列化到第5个属性后停止处理。你需要在服务端的配置文件(web.config/app.config)中调整这个设置:
配置示例:
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="YourServiceBehavior"> <dataContractSerializer maxItemsInObjectGraph="2147483647" /> <!-- 设置为最大整数值 --> <!-- 其他行为配置,比如serviceMetadata等 --> </behavior> </serviceBehaviors> </behaviors> <services> <service name="YourNamespace.YourService" behaviorConfiguration="YourServiceBehavior"> <!-- 服务端点配置 --> </service> </services> </system.serviceModel>
如果是在代码中配置服务行为,也可以通过以下方式设置:
var behavior = new ServiceBehaviorAttribute(); behavior.DataContractSerializer.MaxItemsInObjectGraph = int.MaxValue; host.Description.Behaviors.Add(behavior);
2. 显式指定DataMember的Order属性
当你没有为[DataMember]标记指定Order属性时,DataContractSerializer会按照属性名称的字母顺序来反序列化,而不是你代码中定义的顺序或SOAP请求中的顺序。即使你调整了SOAP请求的属性顺序,序列化器依然会按照自己的预期顺序解析,这可能导致部分属性无法匹配。
修改你的Article类,为每个DataMember显式指定Order,确保和SOAP请求中的顺序一致:
修改后的代码示例:
[DataContract] public class Article { private string _ArticleName; private string _Description; private int _ProductSubGroupNumber; private double _ArticleNumber; private int _Color; private double _Quantity; private int _Version; private int _Material; private int _Warehouse; [DataMember(Order = 1)] public string ArticleName { get { return _ArticleName; } set { _ArticleName = value; } } [DataMember(Order = 2)] public string Description { get { return _Description; } set { _Description = value; } } [DataMember(Order = 3)] public int ProductSubGroupNumber { get { return _ProductSubGroupNumber; } set { _ProductSubGroupNumber = value; } } [DataMember(Order = 4)] public double ArticleNumber { get { return _ArticleNumber; } set { _ArticleNumber = value; } } [DataMember(Order = 5)] public int Color { get { return _Color; } set { _Color = value; } } [DataMember(Order = 6)] public double Quantity { get { return _Quantity; } set { _Quantity = value; } } [DataMember(Order = 7)] public int Version { get { return _Version; } set { _Version = value; } } [DataMember(Order = 8)] public int Material { get { return _Material; } set { _Material = value; } } [DataMember(Order = 9)] public int Warehouse { get { return _Warehouse; } set { _Warehouse = value; } } }
3. 排查属性类型匹配问题
虽然你提到调整顺序后前5个属性都能正常赋值,但还是要确认SOAP请求中的属性值类型和你的实体类类型完全兼容:
- 比如请求中的
ArticleNumber是整数12345,而你的类中是Double类型,虽然.NET可以自动转换,但建议保持类型一致(比如改为Int64或int,如果业务允许); - 检查是否有属性的值超出了对应类型的范围(比如
int类型的属性传入了超过int.MaxValue的值)。
4. 检查属性的get/set逻辑
确认你的实体类中所有属性的get/set方法没有异常逻辑(比如抛出异常、修改其他属性的逻辑),如果反序列化过程中某个属性的set方法抛出未捕获的异常,可能会导致后续属性的反序列化被中断。
按照上面的步骤排查后,应该就能解决你遇到的仅前5个属性被赋值的问题了。
内容的提问来源于stack exchange,提问作者Twiebie

