You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在.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);
    // 处理响应逻辑
}

关键注意事项

  1. 必须使用SOAP 1.2的命名空间(http://www.w3.org/2003/05/soap-envelope),不要混淆SOAP 1.1的命名空间。
  2. 所有业务节点必须显式绑定isw前缀与目标命名空间,避免默认序列化自动生成随机前缀。
  3. 自定义格式化器时需完整重构Envelope结构,确保所有必要的命名空间都声明在根节点上。

内容的提问来源于stack exchange,提问作者ola_olus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 01:17:06