views:

11

answers:

1

I have to call a Web service that is extremely demanding (unstandard) regarding the SOAP message format that it chooses to process. I have no control over the server side implementation and there is no WSDL available, all I have is an intercepted message attached bellow.

My first thought was WCF+MessageContract, but whatever I do with the last, I can't seem to get the right result. Outgoing messages should look like the one bellow. The most tricky part seems to be multiple body contents ("ProxyInfo" and "PayloadInfo" bellow). Besides that I also can not get WCF to remove "Action" element from SOAP message header. I realize that it is a vital element to WCF, but I doubt that I could persuade Web service to accept it. The reply will probably be another story, but I will cross that bridge when I get to it.

Currently I am considering custom serialization and post-/pre- processing of outgoing/incoming messages. In the worst case I guess I will have to do Web requests as well as serialization manually. Please help, I am getting realy desperate...

<?xml version="1.0" encoding="UTF-8" ?>
<e:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://docs.oasisopen.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"&gt;
 <e:Header>
  <ServiceHeader xmlns="http://services/serviceheader" e:actor="http://services/loadbalancer" >
   <ServiceLevel>
    <Type>HIGH</Type>
    <Method>FIFO</Method>
   </ServiceLevel>
  </ServiceHeader>
 </e:Header>
 <e:Body>
  <ProxyInfo xmlns="http://services/proxyinfo"&gt;
   <Server>
    <Address>proxy1:8080</Address>
    <AppId>case_delegator</AppId>
   </Server>
  </ProxyInfo>
  <PayloadInfo xmlns="http://services/payload"&gt;
   <GetConfirmation>
    <CaseId>
     <Id>9728DFC889874CC8B1505D91E33FCFCD</Id>
    </CaseId>
   </GetConfirmation>
  </PayloadInfo>
 </e:Body>
</e:Envelope>
A: 

If you don't want to use Address header you have to use binding without WS-Addressing. In your case use BasicHttpBinding. It will not use WS-Addressing and Action SOAP header but instead it will use SOAPAction HTTP header.

For your message contract try to use something like this:

[DataContract]
public class ServiceHeader
{
  ...
}

[DataContract]
public class ProxyInfo
{
  ...
}

[DataContract]
public class PayloadInfo
{ 
  ...
}

[MessageContract(IsWrapped = false)]
public class Request
{
  [MessageHeader(Namespace="http://services/serviceheader")]
  public ServiceHeader ServiceHeader { get; set; }

  [MessageBodyMember(Namespace="http://services/proxyinfo")]
  public ProxyInfo ProxyInfo { get; set; }

  [MessageBodyMember(Namespace="http://services/payload")]
  public PayloadInfo PayloadInfo { get; set; }
}

The strange thing is the actor attribute in ServiceHeader. Your message doesn't define namespace for prefix e so the message is not valid XML.

Ladislav Mrnka
Thanks, Ladislav! The "IsWrapped=false" part was the one that was missing. Combining that with Namespace declaration on all levels seemed to do the trick, requests are working now.If I could only declare "http://www.w3.org/2001/XMLSchema-instance" Namespace with prefix in one place or even better, not at all (the service does not require it) that would be even better, but for now this part seems to be working and optimization is not top priority :)
Miha Necak