.NET Core C# SOAP客户端请求体非字符串字段丢失问题排查
.NET Core SOAP客户端非字符串字段请求体丢失问题
问题场景
在.NET Core环境下使用C#开发SOAP客户端,核心代码如下:
string endpointURL = "xxxx"; var remoteAddress = new ServiceReference.Endpoint(endpointURL); var bind = new System.ServiceModel.BasicHTTPSBinding(); ServiceReference.ServiceReferenceClient client= new ServiceReference.ServiceReferenceClient(bind, remoteAddress); AddData request = new AddData(); request.authentication = authentication; request.transaction_id = transaction_id; request.subjects = Subjects; request.students = Students; addDataResponse = await client.addData(request);
自动生成的Reference.cs中实体类定义:
public class students { public string name{get;set;} public string @class{get;set;} // class为C#关键字,需加@转义 public bool IsGraduate{get;set;} public int Marks{get;set;} } public class subjects { public string name{get;set;} public string description{get;set;} public bool IsRequired{get;set;} public int Count{get;set;} public int Test{get;set;} }
构造请求时,Subjects和Students已从数据库获取完整数据,调试可见请求对象包含所有字段值,但发送的SOAP请求体仅保留字符串类型字段,bool、int等非字符串字段缺失:
期望的请求体XML:
<?xml version="1.0" encoding="UTF-8"?> <student> <name>Tom Hnaks</name> <class>High</class> <IsGraduate>No</IsGraduate> <Marks>100</Marks> </student> <subjects> <name>Botany</name> <description>High</description> <IsRequired>No</IsRequired> <Test>100</Test> <Count>100</Count> </subjects>
实际的请求体XML:
<?xml version="1.0" encoding="UTF-8"?> <student> <name>Tom Hnaks</name> <class>High</class> </student> <subjects> <name>Botany</name> <description>High</description> </subjects>
原因分析
- 默认序列化规则:.NET Core下的WCF客户端默认使用
DataContractSerializer,对于bool、int等值类型,若字段值为类型默认值(如bool的false、int的0),序列化器会自动忽略这些字段,不写入XML请求体。 - 实体类特性缺失:自动生成的实体类未标记
[DataMember(EmitDefaultValue = true)]特性,无法强制序列化默认值字段。
解决方案
方案1:修改实体类序列化特性
在自动生成的Reference.cs中,为每个非字符串字段添加[DataMember(EmitDefaultValue = true)]特性,同时确保类标记[DataContract]:
[DataContract] public class students { [DataMember] public string name{get;set;} [DataMember] public string @class{get;set;} [DataMember(EmitDefaultValue = true)] public bool IsGraduate{get;set;} [DataMember(EmitDefaultValue = true)] public int Marks{get;set;} } [DataContract] public class subjects { [DataMember] public string name{get;set;} [DataMember] public string description{get;set;} [DataMember(EmitDefaultValue = true)] public bool IsRequired{get;set;} [DataMember(EmitDefaultValue = true)] public int Count{get;set;} [DataMember(EmitDefaultValue = true)] public int Test{get;set;} }
注意:若通过
Add Service Reference更新服务引用,修改会被覆盖,需重新添加特性或用方案2配置。
方案2:更新服务引用时配置序列化选项
添加/更新服务引用时,点击高级按钮,在弹出的对话框中勾选「总是生成消息契约」,或配置EmitDefaultValue为true,让自动生成的代码自带强制序列化特性。
方案3:检查字段实际值
确认非字符串字段的实际值是否为类型默认值(比如Marks是否为0、IsGraduate是否为false),若业务上需要传递默认值,必须通过EmitDefaultValue = true强制序列化。
内容的提问来源于stack exchange,提问作者Navy
相关产品推荐
相关产品推荐

