如何在EndpointReferenceType中添加其他元素(ws-addressing消息信息头)

时间:2017-10-31 13:00:51

标签: c# web-services wcf request-headers ws-addressing

ws-addressing规范中说:

  

2.2。端点参考XML信息集表示

     

/ WSA:EndpointReference的/ {任何}。 这是一种可扩展性机制,允许指定其他元素

请告诉我如何构建这样的XML结构:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:ehkz="https://oag1.dev.mysite.org:11443/addressing" xmlns:wsa="http://www.w3.org/2005/08/addressing">
 <s:Header>
  <ActivityId CorrelationId="114c74b1-3aaf-44c0-9d35-a9479fb9b60a" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">00000000-0000-0000-0000-000000000000</ActivityId>
  <wsa:Action s:mustUnderstand="true">OrganizationQueryRequest</wsa:Action>
  <wsa:MessageID>urn:uuid:a3539897-fc69-4adf-9ae4-1419ccbd7017</wsa:MessageID>
  <wsa:ReplyTo>
     <wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
  </wsa:ReplyTo>
  <wsa:From s:mustUnderstand="true">
     <wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
     <ehkz:organizationID>1.2.398.7.1.9.3.2</ehkz:organizationID>
     <ehkz:applicationID>1.2.398.7.1.5.1.14</ehkz:applicationID>
  </wsa:From>
  <wsa:To s:mustUnderstand="true">https://oag2.dev.mysite.org:11443/Organization</wsa:To>
 </s:Header>
 <s:Body> ... </s:Body>
</s:Envelope>

元素感兴趣:

<wsa:From s:mustUnderstand="true">
 <wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
 <ehkz:organizationID>1.2.398.7.1.9.3.2</ehkz:organizationID>
 <ehkz:applicationID>1.2.398.7.1.5.1.14</ehkz:applicationID>
</wsa:From>

当我尝试重复此操作时,我得到以下结构:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
 <s:Header>
  <ActivityId CorrelationId="594fce7f-a69c-4e9c-aabf-1af8de2fe1fd" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">e2d92b9e-4b56-45ea-b6f7-2d7cf0585f6e</ActivityId>
  <a:Action s:mustUnderstand="1">HCProfessionalQueryRequest</a:Action>
  <a:MessageID>urn:uuid:4e9a056f-5c91-42fb-bf04-4ba4bff5907b</a:MessageID>
  <a:ReplyTo>
   <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
  </a:ReplyTo>
  <a:From>
   <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
   <a:ReferenceParameters>
    <organizationID xmlns="https://oag1.dev.mysite.org:11443/addressing">1.2.398.7.1.9.3.2</organizationID>
    <applicationID xmlns="https://oag1.dev.mysite.org:11443/addressing">1.2.398.7.1.9.1.25</applicationID>
   </a:ReferenceParameters>
  </a:From>
  <a:To s:mustUnderstand="1">https://oag2.dev.mysite.org:11443/Professional</a:To>
 </s:Header>
 <s:Body> ... </s:Body>
</s:Envelope>

元素来自看起来像这样:

<a:From>
 <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
 <a:ReferenceParameters>
  <organizationID xmlns="https://oag1.dev.mysite.org:11443/addressing">1.2.398.7.1.9.3.2</organizationID>
  <applicationID xmlns="https://oag1.dev.mysite.org:11443/addressing">1.2.398.7.1.9.1.25</applicationID>
 </a:ReferenceParameters>
</a:From>

我的其他元素位于参考参数

如何使applicationID和organizationID不能放在ReferenceProperty或ReferenceParameter元素中,而是直接放在WS寻址头的From元素中

这是我的代码:

public class SoapHeaderMessageInspector : IClientMessageInspector
{
    private readonly string _applicationId;
    private readonly string _organizationId;
    private readonly string _soapAction;
    public SoapHeaderMessageInspector(string applicationId, string organizationId, string soapAction = null)
    {
        _applicationId = applicationId;
        _organizationId = organizationId;
        _soapAction = soapAction;
    }
    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        if (request.Version != MessageVersion.Soap11 && request.Version != MessageVersion.Soap12)
        {
            var builder = new EndpointAddressBuilder(new EndpointAddress("http://www.w3.org/2005/08/addressing/anonymous"));
            builder.Headers.Add(AddressHeader.CreateAddressHeader("organizationID", "https://oag1.dev.mysite.org:11443/addressing", _organizationId));
            builder.Headers.Add(AddressHeader.CreateAddressHeader("applicationID", "https://oag1.dev.mysite.org:11443/addressing", _applicationId));

            request.Headers.From = builder.ToEndpointAddress();
        }
        else
        {
            request.Headers.Add(MessageHeader.CreateHeader("organizationID", "https://oag1.dev.mysite.org:11443/addressing", _organizationId, false));
            request.Headers.Add(MessageHeader.CreateHeader("applicationID", "https://oag1.dev.mysite.org:11443/addressing", _applicationId, false));
        }
        if (!string.IsNullOrEmpty(_soapAction))
            request.Headers.Action = _soapAction;
        return null;
    }

    public void AfterReceiveReply(ref Message reply, object correlationState)
    {

    }
}

在web.config中:

<binding name="Custom_Binding_Default">
      <textMessageEncoding messageVersion="Default" />
      <httpsTransport maxBufferPoolSize="20000000" maxReceivedMessageSize="20000000" maxBufferSize="20000000" />
    </binding>

<endpoint address="https://oag2.dev.mysite.org:11443/Organization"
    binding="customBinding" bindingConfiguration="Custom_Binding_Default"
    contract="OrganizationRegistryFeed" name="OrganizationDirectory_Port_Soap" />

1 个答案:

答案 0 :(得分:0)

我知道这个答案可能晚了,但是我遇到了同样的问题,并且能够通过使用继承MessageHeader的类来解决它:

#ifndef GRANDPARENT_H
#define GRANDPARENT_H

struct foo {
    int member;
};

#endif /* GRANDPARENT_H */

然后在您的IClientMessageInspector(SoapHeaderMessageInspector)中:

public class CustomMessageHeader : MessageHeader
{
    private string _Name;

    private string _NameSpace;

    private object _Value;

    private bool _IsReference;

    private string _WsAddressElement;

    private const string _WsAddressNamespace = "http://www.w3.org/2005/08/addressing";

    public CustomMessageHeader(string name, string nameSpace, bool isReference, object value, string wsAdressElement = null)
    {
        _Name = name;
        _NameSpace = nameSpace;
        _Value = value;
        _IsReference = isReference;
        _WsAddressElement = wsAdressElement;
    }

    public override string Name
    {
        get
        {
            return _Name;
        }
    }

    public override string Namespace
    {
        get
        {
            return _NameSpace;
        }
    }

    protected override void OnWriteStartHeader(XmlDictionaryWriter writer, MessageVersion messageVersion)
    {
        if (!string.IsNullOrEmpty(_WsAddressElement))
            writer.WriteStartElement(_WsAddressElement, _WsAddressNamespace);

        if (_IsReference)
            writer.WriteStartElement("ReferenceProperties", _WsAddressNamespace);

        writer.WriteStartElement(_Name, _NameSpace);
    }

    protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
    {          
        writer.WriteValue(_Value);            

        if (_IsReference)
            writer.WriteEndElement();

        if (!string.IsNullOrEmpty(_WsAddressElement))
            writer.WriteEndElement();
    }

}

这将导致您的消息输出为:

public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
    var fromMessageHeader = new CustomMessageHeader("organizationId", "https://oag1.dev.mysite.org:11443/addressing", true, _organizationId, "From");

    request.Headers.Add(fromMessageHeader);
}

但这不是完整的解决方案,并且由于您需要多个ReferenceProperty以及正式的AddressHeader,因此您可能可以继承AddressHeader类并实现以下方法:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
  <s:Header>
    <ActivityId CorrelationId="594fce7f-a69c-4e9c-aabf-1af8de2fe1fd" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">e2d92b9e-4b56-45ea-b6f7-2d7cf0585f6e</ActivityId>
    <a:Action s:mustUnderstand="1">HCProfessionalQueryRequest</a:Action>
    <a:MessageID>urn:uuid:4e9a056f-5c91-42fb-bf04-4ba4bff5907b</a:MessageID>
    <a:ReplyTo>
      <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
    <a:From>
      <a:ReferenceProperties>
        <organizationID xmlns="https://oag1.dev.mysite.org:11443/addressing">1.2.398.7.1.9.3.2</organizationID>
      </a:ReferenceProperties>
    </a:From>
    <a:To s:mustUnderstand="1">https://oag2.dev.mysite.org:11443/Professional</a:To>
 </s:Header>
 <s:Body> ... </s:Body>
</s:Envelope>

我希望这可以帮助将来寻求类似解决方案的人。