How to add SOAP message headers using Rebex custom WCF Binding

0 votes
asked May 17 by Lukas Matyska (42,630 points)

(Note, this was originally asked at comment)

We got an Requirement for OpenUI , that we need to add the Header with credential and session Tokens attribute as part of Request , and parse the Header also after response.

SOAP REQUEST:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cus="http://siebel.com/CustomUI" xmlns:fin="http://www.siebel.com/xml/FindLotInfo">
    <soapenv:Header>
      <UsernameToken xmlns="http://siebel.com/webservices">Username</UsernameToken>
      <PasswordText xmlns="http://siebel.com/webservices">Password</PasswordText>
      <SessionType xmlns="http://siebel.com/webservices">Stateless</SessionType>
   </soapenv:Header>
   <soapenv:Body>
      <cus:ATLFindLotInfoProcess_Input>
         <fin:FindLotInfo>
            <fin:findLotInfoReqData>
           ..................
         </fin:FindLotInfo>
      </cus:ATLFindLotInfoProcess_Input>
   </soapenv:Body>
</soapenv:Envelope>

SOAP RESPONSE:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <SOAP-ENV:Header>
      <siebel-header:SessionToken xmlns:siebel-header="http://siebel.com/webservices">y3dgzHgjMNDAroudyW3FdqDjRzjMJN.cHyU6rOlrsSVJvLrgcCEioOo29u502bo4HSnV3k9s4HhVNCuOP6oXaaUVSUbTaaxpVcNx2eks55Uvk0LCJzVvSBw5AkGUfs-b95OYNVHRGw7SGc49tOpjCRorlqabXXLmhqhnL1y8haqLLZDnZ5ORvQNWj8Q-p1oPG6LhYg1UQWeUf.-GwrR.WN7yLlr8v0kWjXTynLJao3ogQKJytT5ymzAnhJLIrYs8m18McEwFVv09i5K-B1-RvlXhq2t38g3vb3fbCmKyaFoJgy1jP0CcsA__</siebel-header:SessionToken>
   </SOAP-ENV:Header>
   <SOAP-ENV:Body>
      <ns:ATLFindLotInfoProcess_Output xmlns:ns="http://siebel.com/CustomUI">
         <FindLotInfoResponse xmlns="http://www.siebel.com/xml/FindLotInfoResponse">
            <findLotInfoReplyData>
             .......................
         </FindLotInfoResponse>
      </ns:ATLFindLotInfoProcess_Output>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
  • as per above sample Request /Resonse(using soaUI Tool) - I need to add the Header along with Request Body and I need to Parse the Header in Reponse as well.

    Please guide me on this.

  • am using the wcfRequestChannels.cs file which I took from Rebex sample http projects

where we adding header as below

    string action = message.Headers.Action;

    request.Method = "POST";
    request.Headers.Add("SOAPAction", '"' + action + '"');
    request.Headers.Add("Content-Type", "text/xml; charset=utf-8");
  • I need to add further information on this.

Regards
Raj

2 Answers

0 votes
answered 6 days ago by Lukas Matyska (42,630 points)
 
Best answer

I have uploaded new version of RebexWcfBinding with support for custom SOAP headers.

It is available at here.

It introduces new WcfMessageObserver class, which can be used like this:

    var binding = new Rebex.Samples.WcfBinding();
    // configure RequestCreator if necessary
    // binding.RequestCreator.Settings...

    // create service
    var client = new DemoWebServiceSoapClient(binding,
        new EndpointAddress("http://test.rebex.net/demowebservice.asmx"));

    // attach observer for next service call(s)
    using (var observer = new Rebex.Samples.WcfMessageObserver(binding))
    {
        // add some custom headers to outgoing SOAP message(s)
        observer.OutgoingHeaders.Add(new Rebex.Samples.WcfMessageHeader("A", "NS", "Temp1"));
        observer.OutgoingHeaders.Add(new Rebex.Samples.WcfMessageHeader("B", "NS", "Temp2"));

        // call the service
        var response = client.HelloWorld();

        // read SOAP headers of the most recent response
        foreach (var h in observer.IncomingHeaders)
        {
            // h.Name, h.Value, ...
        }
    }

It is also possible to create own IWcfMessageObserver implementation and attach it to WcfBinding.MessageObservers manually.

0 votes
answered May 17 by Lukas Matyska (42,630 points)

The request.Headers.Add() method adds HTTP headers (not SOAP message headers).

To add SOAP message headers, just simply add them to message.Headers collection after line 'message.Headers.Clear();' like this:

message.Headers.Clear();
message.Headers.Add(MessageHeader.CreateHeader("UsernameToken", "http://siebel.com/webservices", "a user name"));
message.Headers.Add(MessageHeader.CreateHeader("PasswordText", "http://siebel.com/webservices", "a password"));
message.Headers.Add(MessageHeader.CreateHeader("SessionType", "http://siebel.com/webservices", "Stateless"));

To read them, just read from responseMessage.Headers collection.

commented May 17 by RajaK (110 points)
thanks Lukas,
 I tried  , since am using WINCE6  with .net3.5 CE  MessageHeader.CreateHeader method expecting 4 arguments - getting below error.

No overload for method 'CreateHeader' takes '3' arguments
- when I check
 public static MessageHeader CreateHeader(string name, string ns, object value, XmlObjectSerializer serializer);

 - we need to pass XmlObjectSerializer  as well .  -  can we get the type of serializer used in Rebex?
commented 6 days ago by Lukas Matyska (42,630 points)
edited 6 days ago by Lukas Pokorny
Oh, I was testing it on desktop, so I didn't realize that .NET CF needs an XmlObjectSerializer.

You can use this:

    internal class MessageHeaderXmlSerializer : XmlObjectSerializer
    {
        private readonly WcfBinding binding;

        public MessageHeaderXmlSerializer(WcfBinding binding)
        {
            this.binding = binding;
        }

        public override bool IsStartObject(XmlDictionaryReader reader)
        {
            throw new NotImplementedException();
        }

        public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
        {
            throw new NotImplementedException();
        }

        public override void WriteEndObject(XmlDictionaryWriter writer)
        {
        }

        public override void WriteObjectContent(XmlDictionaryWriter writer, object graph)
        {
            writer.WriteString(graph.ToString());
        }

        public override void WriteStartObject(XmlDictionaryWriter writer, object graph)
        {
        }
    }


However, I am just working on new version, which will work with headers more easier.

I also realized that headers are not included in responseMessage. The new version will fix this.
commented 6 days ago by RajaK (110 points)
Thank you Lukas - we will wait for your udated build
commented 3 days ago by Lukas Matyska (42,630 points)
I am not sure, whether you noticed it. I have added new answer to this question. The updated build can be downloaded from https://www.rebex.net/getfile/b541b39f9c334407b148786cd6fbdbc4/RebexWcfBinding.zip
commented 3 days ago by RajaK (110 points)
thank you  Lukas ,   can I use existing .dll itself  for above changes?
commented 2 days ago by Lukas Matyska (42,630 points)
You probably mean existing Rebex HTTPS .dll - yes, you can use it.

The RebexWcfBindig sample code is almost unrelated to Rebex HTTPS .dll (if you replace HttpRequestCreator to your transport layer, it will be totally independent on Rebex classes).
commented 1 day ago by RajaK (110 points)
hi Lukas,
   We are using 4  different webservice for my backe end server with different URL.

- in this am creating the binding object for Rebexclient and filling details as below.

     var binding = new Rebex.Samples.WcfBinding();
                binding.RequestCreator.Register();
                binding.RequestCreator.Settings.SslAcceptAllCertificates = true;
                binding.RequestCreator.Settings.SslAllowedVersions = Rebex.Net.TlsVersion.TLS10;


--  PurchaseProductClient  is the object for one of the Webservices.

 PurchaseProductClient = new PurchaseProductSClient(binding, new EndpointAddress(strEndPointUri));

 - could you please any smaple code to add/do not add  the header for webservice as part of rebex client object itself.
commented 1 day ago by Lukas Matyska (42,630 points)
Hi RajaK. I am sorry, I don't understand well, what you need.

Basically, if you have parallel/concurrent environment (more than one service calls could be executed at the same time) create separate Rebex.Samples.WcfBinding instance for each service instance.

If you have non-concurrent environment (only one service call can be executed at a time = service calls are executed one after other) you don't need to add anything special.

In both cases just use the WcfMessageObserver as showed above in case you want to work with SOAP headers:

    using (var observer = new Rebex.Samples.WcfMessageObserver(binding))
    {
        // add custom header to outgoing SOAP message
        observer.OutgoingHeaders.Add(new WcfMessageHeader("Name", "NS", "Value"));

        // call the service
        var response = client.HelloWorld();
    }


I also suggest you to not call binding.RequestCreator.Register() - it is not necessary and  this will affect creation of all WebRequests (not only those in binding).

If you are creating more bindings, I suggest you to create one HttpRequestCreator, then assign it to all your bindings:
binding1.RequestCreator = mainCreator;
binding2.RequestCreator = mainCreator;
binding3.RequestCreator = mainCreator;
commented 1 day ago by RajaK (110 points)
Thank you Lukas, so the
var response = client.HelloWorld();

 - the response will hold the header for response and actual response data. ?
commented 1 day ago by Lukas Matyska (42,630 points)
No, the 'response' is return value of the service (e.g. string in case of "http://test.rebex.net/demowebservice.asmx")

The SOAP message is accessible through IWcfMessageObserver. Please, see sample code in my answer http://forum.rebex.net/8477/how-add-soap-message-headers-using-rebex-custom-wcf-binding?show=8487#a8487

The SOAP headers of the service resonse can be accessed by observer.IncomingHeaders.

You can modify WcfMessageObserver.cs file to catch the SOAP message as well.
...