修改SOAP Header以适配第三方格式的技术求助
问题
我需要创建一个Web服务从第三方企业获取信息,已匹配其SOAP XML格式除Header部分外的内容。我在ASP.NET Web应用中创建了webservice.asmx来处理对方的请求,当前代码及生成的SOAP结构如下:
当前服务代码
[WebService( Namespace = "", Name = "TheRequest")] public class WebService1 : WebService { public HeaderData HeaderData { get; set; } [SoapHeader ("ReplyTo", Required = true)] [WebMethod] public string TheirRequest(string username, string password, string data) { if (HeaderData.To == null || HeaderData.ReplyTo.Address == null || HeaderData.MessageID == null || HeaderData.Action == null) throw new SoapException("Required information not provided", SoapException.ClientFaultCode); if (username.ToLower() == "username" && password.ToLower() == "password") return "SUCCESS"; else throw new SoapException("Unrecognized login", SoapException.ClientFaultCode); } } public class HeaderData : SoapHeader { public string To; public ReplyTo ReplyTo { get; set; } public string MessageID; public string Action; } public class ReplyTo { public string Address; }
当前生成的SOAP结构
<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="" xmlns:xsd="" xmlns:soap=""> <soap:Header> <HeaderData xmlns=""> <To>string</To> <MessageID>string</MessageID> <Action>string</Action> <ReplyTo> <Address>string</Address> </ReplyTo> </HeaderData> </soap:Header> <soap:Body> <TheirRequest xmlns=""> <username>string</username> <password>string</password> <data>string</data> </TheirRequest> </soap:Body> </soap:Envelope>
第三方要求的SOAP格式
<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv=""> <soapenv:Header xmlns:wsa=""> <wsa:To>[customer provided URL]</wsa:To> <wsa:ReplyTo> <wsa:Address>http:...<wsa:Address> </wsa:ReplyTo> <wsa:MessageID>3DBF4F1510689894919</wsa:MessageID> <wsa:Action>urn:submitMessage</wsa:Action> </soapenv:Header> <soapenv:Body> <sub:TheirRequest xmlns:sub=""> <sub:username>customer_provided_username</sub:username> <sub:password>customer_provided_password</sub:password> <sub:data>Base64 encoded XML request</sub:data> </sub:TheirRequest> </soapenv:Body> </soapenv:Envelope>
二者存在两处差异:
<soap:Envelope xmlns:xsi="" xmlns:xsd="" xmlns:soap需要改为<soapenv:Envelope xmlns:soapenv<soap:Header> <HeaderData xmlns="">需要改为<soapenv:Header xmlns:wsa="">
请问能否配置服务以匹配该格式?或能否设置为忽略SOAP Header仅处理Body?
解决方案
一、配置服务匹配第三方SOAP格式
1. 替换SOAP前缀(soap → soapenv)
ASMX默认使用soap作为Envelope前缀,要改成soapenv需要自定义SoapExtension拦截输出流修改XML:
- 创建继承自
SoapExtension的类,在ProcessMessage方法中读取输出流,将所有soap:替换为soapenv:,同时调整Envelope的命名空间声明。 - 在web.config的
<system.web><webServices><soapExtensionTypes>节点注册该扩展类型。
2. 适配WSA命名空间Header
第三方Header使用WS-Addressing(wsa)命名空间,需调整Header类的属性配置:
// 替换原HeaderData和ReplyTo类 [XmlType(Namespace = "第三方实际wsa命名空间URL")] public class WsaHeader : SoapHeader { [XmlElement(ElementName = "To", Namespace = "第三方实际wsa命名空间URL")] public string To { get; set; } [XmlElement(ElementName = "ReplyTo", Namespace = "第三方实际wsa命名空间URL")] public WsaReplyTo ReplyTo { get; set; } [XmlElement(ElementName = "MessageID", Namespace = "第三方实际wsa命名空间URL")] public string MessageID { get; set; } [XmlElement(ElementName = "Action", Namespace = "第三方实际wsa命名空间URL")] public string Action { get; set; } } [XmlType(Namespace = "第三方实际wsa命名空间URL")] public class WsaReplyTo { [XmlElement(ElementName = "Address", Namespace = "第三方实际wsa命名空间URL")] public string Address { get; set; } }
修改WebService类中的Header引用:
public WsaHeader WsaHeader { get; set; } [SoapHeader("WsaHeader", Required = true)] [WebMethod] public string TheirRequest(string username, string password, string data) { if (WsaHeader.To == null || WsaHeader.ReplyTo?.Address == null || WsaHeader.MessageID == null || WsaHeader.Action == null) throw new SoapException("Required information not provided", SoapException.ClientFaultCode); if (username.ToLower() == "username" && password.ToLower() == "password") return "SUCCESS"; else throw new SoapException("Unrecognized login", SoapException.ClientFaultCode); }
同时设置WebService的Namespace为第三方要求的sub命名空间:
[WebService( Namespace = "第三方提供的sub命名空间URL", Name = "TheRequest")]
二、忽略SOAP Header仅处理Body
如果无需校验Header,直接移除SoapHeader相关代码即可:
[WebService( Namespace = "第三方提供的sub命名空间URL", Name = "TheRequest")] public class WebService1 : WebService { [WebMethod] public string TheirRequest(string username, string password, string data) { if (username.ToLower() == "username" && password.ToLower() == "password") return "SUCCESS"; else throw new SoapException("Unrecognized login", SoapException.ClientFaultCode); } }
注意:ASMX默认会忽略未绑定的Header元素,只要Body格式匹配就能正常处理,但需确认第三方是否强制要求Header存在。
内容的提问来源于stack exchange,提问作者Eric Short
相关产品推荐
相关产品推荐

