繁体   English   中英

如何基于生成的代理 class 以编程方式添加 SOAP header

[英]How to programmatically add a SOAP header based on a generated proxy class

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

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

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

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

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

使用下面的代码:

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 的 class。 在该 class 的 OnWriteHeaderContents 中,我们手动将 header 的内容写入代码。 不幸的是,这会导致服务器端出现一些命名空间问题。

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

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

       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;
    }
}

将 clientmessagelogger 添加到 clientruntime:

     [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;
    }
}

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

    [CustContractBehavior]
    public interface IService {
    }

这是服务器收到的 soap 消息: 在此处输入图像描述

要了解有关 IClientMessageInspector 的更多信息,请参阅以下链接:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM