【问题标题】:How to programmatically add a SOAP header based on a generated proxy class如何基于生成的代理类以编程方式添加 SOAP 标头
【发布时间】:2020-05-10 14:27:28
【问题描述】:

我正在尝试使用第三方提供的 SOAP 网络服务。我对该网络服务没有任何控制权。我正在使用名为 OutSystems 的低代码平台使用 Web 服务。遗憾的是,OutSystems 无法识别必须随请求一起发送的 SOAP 标头,因此我必须自己添加它,方法是使用一些自定义 c# 代码扩展平台功能。

SOAP Extensibility API 让我可以访问 WCF ClientCredentials、ServiceEndpoint、IClientChannel 和 CommunicationState 对象。它还提供了一种使用 IEndpointBehavior 对象注册端点行为的方法。

使用 svcutil 我已经能够为消息数据生成代理类,包括我应该添加的 SOAP 标头。

理想情况下,我正在寻找一种方法来实例化标头代理的对象,然后以某种方式将其传递给服务。但这是我卡住的地方。我/我无法找到将该对象用作 SOAP 标头的方法。

OutSytems 的文档还提供了一个关于使用 .net 代码的 adding a soap header 的示例。他们使用 MessageHeader.CreateHeader 创建具有给定元素名称、命名空间和值的新元素。所以这也是我卡住的地方。如果我可以在这里使用代理类,那就太好了,但这只会让我将它设置为值。这样我就得到了一个重复的“根”元素。

使用下面的代码:

class AddSoapHeaderMessageInspector : IClientMessageInspector {

    object IClientMessageInspector.BeforeSendRequest(ref Message request, IClientChannel channel) {
        // before sending a request, add a new SOAP header, specifying its name, namespace and value
        request.Headers.Add(MessageHeader.CreateHeader("MySoapHeader", "http://my-namespace.com", mySOAPHeader));
        return request;
    }

    void IClientMessageInspector.AfterReceiveReply(ref Message reply, object correlationState) {
        // here you would handle the web service response
    }
}

会产生类似 XML 的结果

<MySoapHeader><MySoapHeader><element1><element2></MySoapHeader></MySoapHeader>

虽然它应该看起来像

<MySoapHeader><element1><element2></MySoapHeader>

我们现在的解决方案是我们实现了一个扩展 MessageHeader 的类。在该类的 OnWriteHeaderContents 中,我们在代码中手动编写标头的内容。不幸的是,这会导致服务器端出现一些命名空间问题。

我将其发布在 stackoverflow 而不是 OutSystems 论坛上,因为我认为这更像是一个 WCF/C# 问题而不是 OutSystems 问题。

【问题讨论】:

    标签: c# web-services wcf soap outsystems


    【解决方案1】:

    您可以通过实现IClientMessageInspector接口在实现类中添加soap头。

           public class ClientMessageLogger : IClientMessageInspector
    {
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
    
        }
    
        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            MessageHeader header = MessageHeader.CreateHeader("MySoapHeader", "http://my-namespace.com", "asdas");
            request.Headers.Add(header);
            return null;
        }
    }
    

    将客户端消息记录器添加到客户端运行时:

         [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class, AllowMultiple = false)]
    public class CustContractBehaviorAttribute : Attribute, IContractBehavior, IContractBehaviorAttribute
    {
        public Type TargetContract => throw new NotImplementedException();
    
        public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
            return;
        }
    
        public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            clientRuntime.ClientMessageInspectors.Add(new ClientMessageLogger());
        }
    
        public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
        {
        }
    
        public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
        {
            return;
        }
    }
    

    为代理类的接口添加属性:

        [CustContractBehavior]
        public interface IService {
        }
    

    这是服务器收到的soap消息:

    要了解更多关于 IClientMessageInspector,请参考以下链接:

    https://docs.microsoft.com/en-us/dotnet/api/system.servicemodel.dispatcher.iclientmessageinspector?view=dotnet-plat-ext-3.1

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-27
      • 2023-04-05
      • 2014-03-17
      • 1970-01-01
      • 1970-01-01
      • 2020-10-01
      • 1970-01-01
      相关资源
      最近更新 更多