[英]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 {
}
要了解有关 IClientMessageInspector 的更多信息,请参阅以下链接:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.