C# 生成没有 XML 根元素的 SOAP 信封

Posted

技术标签:

【中文标题】C# 生成没有 XML 根元素的 SOAP 信封【英文标题】:C# Generate SOAP Envelope without XML Root Element 【发布时间】:2021-03-28 03:37:31 【问题描述】:

我使用Message.CreateMessage 创建Message 并将其发送到WCF 服务端点,但我创建的每条消息都以<?xml version="1.0" encoding="utf-16"?> 开头,这导致服务拒绝我的Operation is not supported 消息。 SOAP 1.1 standard 声明 The Envelope is the top element of the XML document representing the message. 这可能是服务拒绝我的消息的原因。不同的 MessageVersions 不会更改生成的 XML,构造函数确实接受 BodyWriter 但 XML 正文不会导致我的问题,它是根元素。

有没有一种方法可以在没有 XML 根元素的情况下生成带有 Message.CreateMessageMessage

代码

internal static Message CreateGetMessage(string id)

    const string Get = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Get";
    const string Rm = "http://schemas.microsoft.com/2006/11/ResourceManagement";

    /* unnecessary code removed to create simplest example */

    var message = Message.CreateMessage(MessageVersion.Default, Get);

    if (message.Headers.FindHeader("ResourceReferenceProperty", Rm) <= 0)
    
        message.Headers.Add(MessageHeader.CreateHeader("ResourceReferenceProperty", Rm, id));
    

    return message;

生成的 SOAP 信封

<?xml version="1.0" encoding="utf-16"?>
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
    <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</a:Action>
    <ResourceReferenceProperty xmlns="http://schemas.microsoft.com/2006/11/ResourceManagement">8f2a4ecc-e3dc-1a4c-5a28-4a4a7a8e6644</ResourceReferenceProperty>
</s:Header>
<s:Body />
</s:Envelope>

所需的 SOAP 信封

<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
    <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</a:Action>
    <ResourceReferenceProperty xmlns="http://schemas.microsoft.com/2006/11/ResourceManagement">8f2a4ecc-e3dc-1a4c-5a28-4a4a7a8e6644</ResourceReferenceProperty>
</s:Header>
<s:Body />
</s:Envelope>

调试

【问题讨论】:

我发现删除 utf-16 错误的唯一方法是使用 readline 跳过处理该行。以以下答案为例:***.com/questions/65331628/… &lt;?xml version="1.0" encoding="utf-16"?&gt; 不是根元素,它是XML declaration。我确实找到了WCF Change message encoding from Utf-16 to Utf-8 和Can you change the XML Declaration of a WCF Client Request? If so, how?,你可以检查一下是否有帮助。 【参考方案1】:

可以使用.NET提供的Message Formatter自定义SOAP消息,在服务端实现IDispatchMessageFormatter接口,在客户端实现IClientMessageFormatter接口。这是推荐的方法。

还有一个消息检查器来修改 SOAP 消息。这是消息检查器的示例。

 public class CustomMessageInspector : IDispatchMessageInspector
    
        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        
            MessageHeader header = MessageHeader.CreateHeader("UserAgent", "http://User", "User1");
            request.Headers.Add(header);
            return null;
        

        public void BeforeSendReply(ref Message reply, object correlationState)
        
            MessageHeader header1 = MessageHeader.CreateHeader("Testreply", "http://Test", "Test");
            reply.Headers.Add(header1);
        
    
    [AttributeUsage(AttributeTargets.Interface)]
    public class CustomBehavior : Attribute, IContractBehavior
    
        public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        
            return;
        

        public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        
            return;
        
        public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
        
            dispatchRuntime.MessageInspectors.Add(new CustomMessageInspector());
        

        public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
        
            return;
        
    

将 CustomBehavior 添加到您的服务合同以进行应用。

 [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
    [CustomBehavior]

如果消息拦截器修改了服务合约定义的消息体,内容验证会失败,所以建议只修改消息头。

【讨论】:

以上是关于C# 生成没有 XML 根元素的 SOAP 信封的主要内容,如果未能解决你的问题,请参考以下文章

PHP/SOAP/XML 文档中根元素之前的标记必须格式正确

xml SFMC DataExtensionField检索SOAP信封

XSLT转换需要添加SOAP信封并在SOAP标头和正文之间拆分XML

删除标题标签,包括信封,正文等

如果命名空间声明在 SOAP 信封上,如何使用 JAXB 解组 SOAP 响应?

如何使用目标 c 从 xml 信封中提取 xml 肥皂体?