0

In ws-addressing specification says that:

2.2. Endpoint Reference XML Infoset Representation

/wsa:EndpointReference/{any}. This is an extensibility mechanism to allow additional elements to be specified.

Please tell me how to build such a XML structure:

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

the From element is of interest:

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

when I try to repeat this, I get the following structure:

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

element From looks like that:

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

My additional elements are placed under the ReferenceParameters

How to make it so that applicationID and organizationID shall not be placed within ReferenceProperty or ReferenceParameter element but directlly within From element of WS addressing header

Here is my code:

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)
    {

    }
}

In 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" />
Chelfree
  • 9
  • 4

1 Answers1

0

I know this answer is probably late but I had the same issue and was able to resolve it by using a class inheriting the MessageHeader:

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

}

Then in your IClientMessageInspector (SoapHeaderMessageInspector):

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

This will result in your message output being:

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

It is not the complete solution however and as your requirement is for multiple ReferenceProperties as well as the formal AddressHeader, you could potentially inherit the AddressHeader class instead and implement the following methods:

protected abstract void OnWriteAddressHeaderContents(XmlDictionaryWriter writer);

protected virtual void OnWriteStartAddressHeader(XmlDictionaryWriter writer);

I hope this helps someone looking for a similar solution in the future.

Flatpete
  • 1
  • 2