如何在.NET Core中使用SoapCore生成指定SOAP客户端请求
生成指定格式SOAP客户端请求的可行方案
目标是生成如下格式的SOAP请求:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:isw="http://tech.solhavensystems.com/customerenquiry/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body> <isw:CustomerEnquiry> <isw:CustomerEnquiryRequest> <isw:CustomerID>012345678</isw:CustomerID> </isw:CustomerEnquiryRequest> </isw:CustomerEnquiry> </soap:Body> </soap:Envelope>
核心配置要点
要匹配这个格式,关键是处理命名空间前缀、SOAP版本(此处为SOAP 1.2),以及确保所有业务节点统一使用isw前缀。
步骤1:定义带指定命名空间的服务与数据契约
显式给服务接口和数据模型绑定目标命名空间,确保序列化时的基础命名空间正确:
[ServiceContract(Namespace = "http://tech.solhavensystems.com/customerenquiry/")] public interface ICustomerEnquiryService { [OperationContract( Action = "http://tech.solhavensystems.com/customerenquiry/CustomerEnquiry", ReplyAction = "http://tech.solhavensystems.com/customerenquiry/CustomerEnquiryResponse" )] CustomerEnquiryResponse CustomerEnquiry(CustomerEnquiryRequest request); } [DataContract(Namespace = "http://tech.solhavensystems.com/customerenquiry/")] public class CustomerEnquiryRequest { [DataMember] public string CustomerID { get; set; } } [DataContract(Namespace = "http://tech.solhavensystems.com/customerenquiry/")] public class CustomerEnquiryResponse { // 按需定义响应字段 }
步骤2:自定义消息格式化器(WCF客户端场景)
默认WCF序列化可能出现命名空间前缀不统一、Envelope声明不全的问题,需自定义格式化器强制调整XML结构:
public class CustomSoapFormatter : IClientMessageFormatter { private readonly IClientMessageFormatter _innerFormatter; private readonly string _targetNs; private const string _prefix = "isw"; public CustomSoapFormatter(IClientMessageFormatter innerFormatter, string targetNs) { _innerFormatter = innerFormatter; _targetNs = targetNs; } public Message SerializeRequest(MessageVersion messageVersion, object[] parameters) { // 先获取默认序列化的消息 var originMsg = _innerFormatter.SerializeRequest(messageVersion, parameters); var xmlDoc = new XmlDocument(); using (var ms = new MemoryStream()) { originMsg.WriteBodyContents(XmlWriter.Create(ms)); ms.Position = 0; xmlDoc.Load(ms); } // 重新构建符合要求的SOAP Envelope var envelope = xmlDoc.CreateElement("soap", "Envelope", "http://www.w3.org/2003/05/soap-envelope"); envelope.SetAttribute($"xmlns:{_prefix}", _targetNs); envelope.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); envelope.SetAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema"); // 构建Body并修正所有业务节点的前缀 var body = xmlDoc.CreateElement("soap", "Body", "http://www.w3.org/2003/05/soap-envelope"); var operationNode = xmlDoc.DocumentElement.FirstChild; operationNode.Prefix = _prefix; foreach (XmlNode child in operationNode.ChildNodes) { child.Prefix = _prefix; foreach (XmlNode grandChild in child.ChildNodes) { grandChild.Prefix = _prefix; } } body.AppendChild(operationNode); envelope.AppendChild(body); xmlDoc.AppendChild(envelope); // 返回重构后的消息 return Message.CreateMessage(messageVersion, null, new XmlNodeReader(xmlDoc)); } public object DeserializeReply(Message message, object[] parameters) { return _innerFormatter.DeserializeReply(message, parameters); } }
步骤3:给客户端端点绑定自定义格式化器
通过端点行为将自定义格式化器注入到客户端调用流程中:
// 配置SOAP 1.2绑定 var binding = new BasicHttpsBinding(BasicHttpsSecurityMode.Transport); binding.MessageVersion = MessageVersion.Soap12; var endpoint = new EndpointAddress("你的服务地址"); var client = new CustomerEnquiryServiceClient(binding, endpoint); // 添加自定义行为 client.Endpoint.Behaviors.Add(new CustomFormatterBehavior(_targetNs)); // 发起调用 var request = new CustomerEnquiryRequest { CustomerID = "012345678" }; var response = client.CustomerEnquiry(request);
配套的行为类实现:
public class CustomFormatterBehavior : IEndpointBehavior { private readonly string _targetNs; public CustomFormatterBehavior(string targetNs) { _targetNs = targetNs; } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { foreach (var operation in clientRuntime.Operations) { operation.Formatter = new CustomSoapFormatter(operation.Formatter, _targetNs); } } // 其他接口方法空实现 public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { } public void Validate(ServiceEndpoint endpoint) { } }
步骤4:SoapCore客户端手动构建方案(.NET Core场景)
如果使用SoapCore且不想依赖WCF框架,可以直接手动构建XML结构:
var client = new HttpClient(); var xmlDoc = new XmlDocument(); // 构建Envelope var envelope = xmlDoc.CreateElement("soap", "Envelope", "http://www.w3.org/2003/05/soap-envelope"); envelope.SetAttribute("xmlns:isw", "http://tech.solhavensystems.com/customerenquiry/"); envelope.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); envelope.SetAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema"); // 构建Body及业务节点 var body = xmlDoc.CreateElement("soap", "Body", "http://www.w3.org/2003/05/soap-envelope"); var enquiryNode = xmlDoc.CreateElement("isw", "CustomerEnquiry", "http://tech.solhavensystems.com/customerenquiry/"); var requestNode = xmlDoc.CreateElement("isw", "CustomerEnquiryRequest", "http://tech.solhavensystems.com/customerenquiry/"); var idNode = xmlDoc.CreateElement("isw", "CustomerID", "http://tech.solhavensystems.com/customerenquiry/"); idNode.InnerText = "012345678"; // 组装节点 requestNode.AppendChild(idNode); enquiryNode.AppendChild(requestNode); body.AppendChild(enquiryNode); envelope.AppendChild(body); xmlDoc.AppendChild(envelope); // 发送请求 using (var ms = new MemoryStream()) { xmlDoc.Save(ms); ms.Position = 0; var content = new StreamContent(ms); content.Headers.ContentType = new MediaTypeHeaderValue("application/soap+xml"); var response = await client.PostAsync("你的服务地址", content); // 处理响应逻辑 }
关键注意事项
- 必须使用SOAP 1.2的命名空间(
http://www.w3.org/2003/05/soap-envelope),不要混淆SOAP 1.1的命名空间。 - 所有业务节点必须显式绑定
isw前缀与目标命名空间,避免默认序列化自动生成随机前缀。 - 自定义格式化器时需完整重构Envelope结构,确保所有必要的命名空间都声明在根节点上。
内容的提问来源于stack exchange,提问作者ola_olus
相关产品推荐
相关产品推荐

