I have just started a project to replace an old CRM system by Oracle CRM on demand. The old system integrates with several systems by exporting and importing either XML or CSV files via a BizTalk interchange.The Oracle CRM on Demand system communicates other systems via web services instead of file imports and exports. New interfaces where required between BizTalk and the Oracle CRM on demand web services.
The first task was to consume the Oracle CRM web service and configure the WCF send adapters. This is what this post will describe.
The custom WSDL’s can be exported from the Oracle CRM on demand application using a wizard.
Consuming this WSDL using the BizTalk WCF Service publishing wizard generates the schemas and binding files for the web service. All the Oracle CRMOD endpoints use WS-security for user authentication and I knew it would take me some time to work out the correct WCF binding to use. I tried several standard WCF binding with no success e.g..
WCF WSHTTP Basic HTTP binding with Transport and message security
Message sent from WCF tracing
<s:Envelope xmlns:s=”http://www.w3.org/2003/05/soap-envelope“><s:Header><a:Action s:mustUnderstand=”1” xmlns:a=”http://www.w3.org/2005/08/addressing“>http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT</a:Action><a:MessageID xmlns:a=”http://www.w3.org/2005/08/addressing“>urn:uuid:11e7f2da-306d-479f-9fa4-90b72de604df</a:MessageID>ActivityId CorrelationId=”677e65ea-fa95-4639-b9bc-120e59604916” xmlns=”http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics“>0ca86810-4c66-4145-8666-4d686ed25b65</ActivityId><a:ReplyTo xmlns:a=”http://www.w3.org/2005/08/addressing“><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo><a:To s:mustUnderstand=”1” xmlns:a=”http://www.w3.org/2005/08/addressing“>https://secure-vmsomxmla.crmondemand.com/Services/Integration</a:To><o:Security s:mustUnderstand=”1” xmlns:o=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd“><u:Timestamp u:Id=”_0” xmlns:u=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd“><u:Created>2011-08-14T22:13:41.689Z</u:Created><u:Expires>2011-08-14T22:18:41.689Z</u:Expires></u:Timestamp><o:UsernameToken u:Id=”uuid-eb498020-1e4d-4b2e-a1c1-1d42c33112c1-1” xmlns:u=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd“><o:Username><!– Removed–></o:Username><o:Password><!– Removed–></o:Password></o:UsernameToken></o:Security></s:Header></s:Envelope>
I got the same non descript message back from OracleCRMOD namely;
A message sent to adapter “WCF-Custom” on send port “WcfSendPort_OracleCRMOD_Account_Custom” with URI “https://secure-vmsomxmla.crmondemand.com/Services/Integration” is suspended.
Error details: System.ServiceModel.ProtocolException: The remote server returned an unexpected response: (400) Bad Request. —> System.Net.WebException: The remote server returned an error: (400) Bad Request.
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)
— End of inner exception stack trace —
Finally I used SOAPUI to work out what the correct SOAP header was to send. I discovered that the SOAP header should look like;
Successful SOAPUI
<soapenv:Envelope xmlns:acc=”urn:crmondemand/ws/ecbs/account/” xmlns:quer=”urn:/crmondemand/xml/Account/Query” xmlns:soapenv=”http://schemas.xmlsoap.org/soap/envelope/”><soapenv:Header><wsse:Security soapenv:mustUnderstand=”1″ xmlns:wsse=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd”><wsse:UsernameToken wsu:Id=”UsernameToken-1″ xmlns:wsu=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd”><wsse:Username>DTACOMSV/MARKBRI@DATACOM.CO.NZ</wsse:Username><wsse:Password Type=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText”>NotmyPassword</wsse:Password><wsse:Nonce EncodingType=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary”>uMuUPmiIyuy+psyChG0OMw==</wsse:Nonce><wsu:Created>2011-08-14T20:21:45.905Z</wsu:Created></wsse:UsernameToken></wsse:Security></soapenv:Header><soapenv:Body><acc:AccountQueryPage_Input><quer:ListOfAccount pagesize=”25″><quer:Account searchspec=”[AccountName] LIKE ‘M*'”><quer:AccountName/><quer:ModifiedDate/></quer:Account> </quer:ListOfAccount><acc:LOVLanguageMode>LIC</acc:LOVLanguageMode><acc:ViewMode>Manager</acc:ViewMode></acc:AccountQueryPage_Input></soapenv:Body></soapenv:Envelope>
Next i imported the custom binding that has been created by the BizTalk wizard and started to change the parameters while running a WCF trace. By trial and error I compared the SOAP message from the WCF trace with that of the SOAP UI message. The example below was close but I was still getting that annoying ‘The remote server returned an unexpected response: (400) Bad Request.“ from OracleCRMOD.
WCF Custom binding BizTalk SOAP11WSAddressingAugust2004
SOAP trace
<s:Envelope xmlns:s=”http://schemas.xmlsoap.org/soap/envelope/”><s:Header><a:Action s:mustUnderstand=”1″ xmlns:a=”http://schemas.xmlsoap.org/ws/2004/08/addressing”>document/urn:crmondemand/ws/ecbs/account/:AccountQueryPage</a:Action><a:MessageID xmlns:a=”http://schemas.xmlsoap.org/ws/2004/08/addressing”>urn:uuid:c8def1ae-7419-4c23-b338-954a6de815e1</a:MessageID><ActivityId CorrelationId=”ccba640e-7de2-490e-b7d2-643884dc9a5b” xmlns=”http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics”>df5139b9-1dd6-4f72-ae5c-cdb3b616690a</ActivityId><a:ReplyTo xmlns:a=”http://schemas.xmlsoap.org/ws/2004/08/addressing”><a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><a:To s:mustUnderstand=”1″ xmlns:a=”http://schemas.xmlsoap.org/ws/2004/08/addressing”>https://secure-vmsomxmla.crmondemand.com/Services/Integration</a:To><o:Security s:mustUnderstand=”1″ xmlns:o=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd”><u:Timestamp u:Id=”_0″ xmlns:u=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd”><u:Created>2011-08-12T04:08:39.481Z</u:Created><u:Expires>2011-08-12T04:13:39.481Z</u:Expires></u:Timestamp><o:UsernameToken u:Id=”uuid-13511941-7a77-4476-8fb1-18b73414e80e-6″ xmlns:u=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd”><o:Username><!– Removed–></o:Username><o:Password><!– Removed–></o:Password></o:UsernameToken></o:Security></s:Header></s:Envelope>
The next thing I did was to remove the addressing by changing the message version to Soap11.
WCF Custom binding BizTalk SOAP11
<s:Envelope xmlns:s=”http://schemas.xmlsoap.org/soap/envelope/” xmlns:u=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd“><s:Header><ActivityId CorrelationId=”46a55bc7-8e6e-4929-935d-0a61eb464c5f” xmlns=”http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics“>bd4ec745-2d98-443c-882d-ba236764b500</ActivityId><o:Security s:mustUnderstand=”1” xmlns:o=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd“><o:UsernameToken u:Id=”uuid-6aacf4ca-43f8-47f5-a06f-178be2d2cf11-1“><o:Username><!– Removed–></o:Username><o:Password><!– Removed–></o:Password></o:UsernameToken></o:Security></s:Header><s:Body><ns0:AccountQueryPage_Input xmlns:ns0=”urn:crmondemand/ws/ecbs/account/“><ns1:ListOfAccount pagesize=”25” xmlns:ns1=”urn:/crmondemand/xml/Account/Query“><ns1:Account searchspec=”[AccountName] LIKE ‘M*’“><ns1:AccountName></ns1:AccountName><ns1:ModifiedDate></ns1:ModifiedDate><ns1:Location></ns1:Location></ns1:Account></ns1:ListOfAccount><ns0:LOVLanguageMode>LIC</ns0:LOVLanguageMode><ns0:ViewMode>Manager</ns0:ViewMode></ns0:AccountQueryPage_Input></s:Body></s:Envelope>
Close but I was still getting that annoying ‘The remote server returned an unexpected response: (400) Bad Request.“ from OracleCRMOD. Finally I changed include timestamp to false and it worked! Thanks to Nick Wong.
The moral of this story is that configuring WCF-custom adapter requires careful analysis using WCF tracing and quite a bit of luck!