4

I've run into an issue where the Savon Ruby Gem generates a SOAP API call that fails, however when I copy and paste the exact same XML message into SOAP-UI it succeeds.

I send this message:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tem="http://tempuri.org/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:vis="http://schemas.datacontract.org/2004/07/Vision.SecureOriginCommand.ServiceContracts">
<soapenv:Body>
  <tem:CameraConfiguration>
  <tem:request>
   <vis:ClientToken>5555</vis:ClientToken>
   <vis:DeviceID>26219</vis:DeviceID>
    <vis:Enabled>1</vis:Enabled>
    <vis:Interval>60</vis:Interval>
  </tem:request>
 </tem:CameraConfiguration>
</soapenv:Body>

To this API (A remote web camera configuration): https://oapqa.onasset.com/Services/SecureOriginCommand.svc?wsdl

But it fails with this message:

 SOAP response (status 500):
 <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
 <s:Body>
 <s:Fault><faultcode xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:ActionNotSupported</faultcode>
<faultstring xml:lang="en-US">The message with Action 'oapSetSentryReportingIntervalRequest' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver.  Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None)</faultstring>
 </s:Fault>
</s:Body>

My first thought was that I must have made a typo in the action name. But no, when I try the exact same message in SOAP-UI I get the following success:

  <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
  <CameraConfigurationResponse xmlns="http://tempuri.org/">
     <CameraConfigurationResult xmlns:a="http://schemas.datacontract.org/2004/07/Vision.SecureOriginCommand.ServiceContracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <a:Error/>
        <a:Result>true</a:Result>
     </CameraConfigurationResult>
  </CameraConfigurationResponse>
 </s:Body>
</s:Envelope>

This leads me to believe that the issue is not being caused by the format of my xml message but with the way I'm configuring my client. Here is the actual code:

Savon.configure do |config|
 config.log = :debug
 config.env_namespace = :soapenv
 config.raise_errors = false
end

# TODO Enable ssl certficate verification
client = Savon::Client.new do
  wsdl.document = TARGET_SO_WSDL
  http.auth.ssl.verify_mode = :none
end

resp = client.request 'tem', 'CameraConfiguration' do
  soap.namespaces['xmlns:vis'] = 'http://schemas.datacontract.org/2004/07/Vision.SecureOriginCommand.ServiceContracts'
  soap.namespaces['xmlns:tem'] = 'http://tempuri.org/'
  soap.body = {
    'tem:request' => {
      'vis:ClientToken' => ON_ASSET_API_KEY,
      'vis:DeviceID' => webcam.gps_device.device_id,
      'vis:Enabled' => 1, 
      'vis:Interval' => webcam.report_interval
    }
  }
end

I've spoken to the developer who maintains the API I'm trying to access. I thought his response could provide a clue:

Binding on the RemoteSentryService was set to mexHttpBinding instead of mexHttpsBinding.


I don’t think this should give you a fault exception, because its working  on .NET simulator client I have. And this endpoint is only used to generate the wsdl (MetaExchange Binding). But, given you are using a different client, I would still give it a shot.

I also regenerated the proxy from wsdl and updated my sample simulator and it looks good.

Is this issue a known issue with Savon and Microsoft SOAP endpoints or HTTPS? Or is this issue something only I'm encountering?

Frank
  • 18,432
  • 9
  • 30
  • 30

1 Answers1

5

Debugged it and noticed that Savon unfortunately doesn't send the correct SOAPAction HTTP header. FYI: After sending a SOAP request via soapUI, you can click on the "RAW" tab (vertically aligned on the request window) to investigate further.

Here's the complete example:

client = Savon::Client.new do
  wsdl.document = TARGET_SO_WSDL
  http.auth.ssl.verify_mode = :none
end

resp = client.request 'tem', 'CameraConfiguration' do
  # Notice, that the SOAPAction needs to the wrapped in double quotes:
  http.headers['SOAPAction'] = %("http://tempuri.org/ISecureOriginCommand/CameraConfiguration")
  soap.namespaces['xmlns:vis'] = 'http://schemas.datacontract.org/2004/07/Vision.SecureOriginCommand.ServiceContracts'
  soap.body = {
    'tem:request' => {
      'vis:ClientToken' => 5555,
      'vis:DeviceID' => 26219,
      'vis:Enabled' => 1, 
      'vis:Interval' => 60
    }
  }
end

Hope it works for you!

rubiii
  • 6,903
  • 2
  • 38
  • 51
  • 1
    This looks like it works. Thank you. I truly appreciate you taking the time to debug, that's very kind of you. And thanks for the soap-UI tip. – Frank Jan 26 '12 at 15:02
  • 1
    Wow, this was my exact problem. Thanks a million for posting. So is this a bug in Savon or some kind of interoperability problem? – David van Geest May 09 '12 at 20:27