KevinM KevinM - 2 months ago 20
Ruby Question

Savon with a custom binding

I have the lovely task of working with a hefty SOAP api with Rails. The SOAP service has three different bindings; wsHttpBinding, wsHttpBinding with x509, and a custom binding. I'm able to hit two of the end points with just wsHttpBinding, but the third requires a username and password, which isn't working with that. I'm avoiding the x509 because of the cert, and the custom binding works great in SoapUI, but with Savon I get the below error.


The message with Action '' 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).


I've taken the exact XML that is generated with Savon and put it in SoapUI and it works.

Could this be a binding issue? And is there a way to tell it to use this custom binding?

Here is the custom binding I've found in the App.config

<bindings>
<customBinding>
<binding name="cust">
<textMessageEncoding messageVersion="Soap12" />
<httpTransport />
</binding>
<binding name="cust1">
<textMessageEncoding messageVersion="Soap12" />
<httpTransport />
</binding>
<binding name="cust2">
<textMessageEncoding messageVersion="Soap12" />
<httpTransport />
</binding>
</customBinding>
</bindings>
<endpoint address="http://api.xyz.com/stuff.svc/cust"
binding="customBinding" bindingConfiguration="cust" contract="stuff.Xstuff"
name="cust" />





Edit #1

Here is my current client setup incase it helps.

@client = Savon.client(
wsdl: 'http://api.xyz.com/stuff.svc?wsdl',
wsse_auth: %w'username password',
wsse_timestamp: true,
raise_errors: false,
log: true,
log_level: :debug,
soap_version: 2,
pretty_print_xml: true,
convert_request_keys_to: :none,
use_wsa_headers: true,
headers: {'Content-Type' => 'application/soap+xml; charset=utf-8'}





Edit #2

I found the issue. Savon wasn't setting the action in the Content-Type like SoapUI was. Thanks to @RicardoPontual for suggesting to try to compare the Savon and SoapUI request again, this caused me to look at it closer and notice the issue.

headers: {'Content-Type' => 'application/soap+xml;charset=UTF-8;action="tempuri.org/stuf‌​f/set_table_stuff"'}

Answer

Based in what we talked in comments, adding the header with the action of the operation you wanna consume may resolve the issue, something like this:

@client = Savon.client(
      wsdl: 'http://api.xyz.com/stuff.svc?wsdl',
      wsse_auth: %w'username password',
      wsse_timestamp: true,
      raise_errors: false,
      log: true,
      log_level: :debug,
      soap_version: 2,
      pretty_print_xml: true,
      convert_request_keys_to: :none,
      use_wsa_headers: true,
      headers: {'Content-Type' => 'application/soap+xml;charset=UTF-8;action="tempuri.org/stuf‌​f/set_table_stuff"'}
      );
Comments