WCF SOAP服务适配指定契约的SOAP请求格式问题求助
WCF服务适配指定SOAP请求解决方案
参考报文
目标适配SOAP请求
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sen="http://sender.v1.datineo.push.ws.nicbase.com/"> <soapenv:Header/> <soapenv:Body> <sen:PushDataArray> <!--Zero or more repetitions:--> <pushDataArray> <assetId>?</assetId> <!--Optional:--> <assetName>?</assetName> <!--Zero or more repetitions:--> <boxData> <boxId>?</boxId> <provider>?</provider> <gateway>?</gateway> <!--Optional:--> <timestamp>?</timestamp> <!--Optional:--> <timeReceived>?</timeReceived> <!--Optional:--> <gpsData> <!--Optional:--> <timestamp>?</timestamp> <latitude>?</latitude> <longitude>?</longitude> <!--Optional:--> <location>?</location> <!--Optional:--> <height>?</height> <!--Optional:--> <direction>?</direction> <!--Optional:--> <heading>?</heading> <!--Optional:--> <distance>?</distance> <!--Optional:--> <totalDistance>?</totalDistance> <!--Optional:--> <speed>?</speed> <!--Optional:--> <satellites>?</satellites> </gpsData> </boxData> <!--Optional:--> <externalCustomerIdentification>?</externalCustomerIdentification> </pushDataArray> </sen:PushDataArray> </soapenv:Body> </soapenv:Envelope>
当前实现生成的SOAP报文
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sen="http://sen.company.com"> <soapenv:Header/> <soapenv:Body> <sen:datineoV1> <!--Optional:--> <sen:datineoV1Data> <!--Zero or more repetitions:--> <sen:PushDataArray> <assetId>?</assetId> <!--Optional:--> <assetName>?</assetName> <!--Optional:--> <boxData> <!--Optional:--> <boxId>?</boxId> <!--Optional:--> <provider>?</provider> <!--Optional:--> <gateway>?</gateway> <timestamp>?</timestamp> <timeReceived>?</timeReceived> <!--Optional:--> <gpsData> <timestamp>?</timestamp> <latitude>?</latitude> <longitude>?</longitude> <height>?</height> <!--Optional:--> <location>?</location> <direction>?</direction> <heading>?</heading> <distance>?</distance> <totalDistance>?</totalDistance> <speed>?</speed> <satellites>?</satellites> </gpsData> </boxData> <!--Optional:--> <externalCustomerIdentification>?</externalCustomerIdentification> </sen:PushDataArray> </sen:datineoV1Data> </sen:datineoV1> </soapenv:Body> </soapenv:Envelope>
核心差异点
- 命名空间不匹配:目标SOAP的sen前缀对应命名空间为
http://sender.v1.datineo.push.ws.nicbase.com/,当前实现使用的是http://sen.company.com - 报文结构多层嵌套:目标Body下直接是
<sen:PushDataArray>根节点,子节点直接是重复的<pushDataArray>;当前实现多了<sen:datineoV1>、<sen:datineoV1Data>两层嵌套,数组元素还带了sen命名空间前缀 - 数组外层多了默认容器:WCF默认序列化数组时会自动包裹一层父节点,和目标结构不符
解决步骤
步骤1:修改服务契约命名空间
将服务契约的命名空间修改为目标要求的命名空间:
[ServiceContract(Namespace = "http://sender.v1.datineo.push.ws.nicbase.com/")] [XmlSerializerFormat] public interface IDataImportSoapService { // 后续修改操作契约 }
步骤2:新增请求包装类,去除数组外层容器
不要直接用数组作为接口入参,新增一个请求类控制根节点名称,同时给数组属性加[XmlElement]特性去掉外层容器:
// 新增请求根节点类 [XmlRoot(ElementName = "PushDataArray", Namespace = "http://sender.v1.datineo.push.ws.nicbase.com/")] public class PushDataArrayRequest { // 加XmlElement特性,直接将数组元素序列化为<pushDataArray>节点,无外层容器 [XmlElement(ElementName = "pushDataArray", Namespace = "")] public PushDataArray[] Items { get; set; } }
步骤3:修改操作契约适配新的入参
调整接口方法的入参和配置,避免生成多余的嵌套节点:
[OperationContract] [WebInvoke(Method = "POST", UriTemplate = "datineoV1", BodyStyle = WebMessageBodyStyle.Bare)] DatineoV1Response datineoV1(PushDataArrayRequest request);
步骤4:可选调整(按需开启)
如果需要调整字段的必填/可选特性,可给对应属性加IsNullable = true配置,和目标SOAP的可选注释对齐:
[XmlElement(ElementName = "assetName", Namespace = "", IsNullable = true)] public string assetName { get; set; }
验证效果
修改后生成的SOAP报文将完全匹配目标结构:
- Body下直接是
<sen:PushDataArray>根节点,命名空间符合要求 - 根节点下直接是重复的
<pushDataArray>子节点,无多余嵌套 - 所有业务字段无命名空间前缀,和目标一致
内容的提问来源于stack exchange,提问作者Tomb86
相关产品推荐
相关产品推荐

