无法让Savon形成正确的XML

Zac*_*lis 2 ruby soap wsdl savon

我之前使用过SOAP,但很多年前,如果我能帮助它,我会尽量保持清醒.

短篇故事...

  • 使用"Soap Client"OS X应用程序,我可以得到我想要的响应.
  • 如果我使用client.request :foo_web_serivce, :language_count, :body => { :foo_app_id => "...", :session_id => "..." }然后我得到一个,Status 200但我的结果是-1因为我认为app_id无法识别.
  • 如果我尝试复制Soap Client call(<LanguageCount>)而不是Savon的call(<foo_web_service:LanguageCount>),那么我得到一个Status 500.

请提前告知并提前致谢.

很长的故事...

使用SOAP客户端我可以看到正确的请求XML是:

User-Agent: Mac OS X; WebServicesCore (357)
Content-Type: text/xml
Host: redacted
Soapaction: http://tempuri.org/redacted/LanguageCount

<?xml version="1.0" encoding="utf-8"?>
  <SOAP-ENV:Envelope
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
    SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
      <SOAP-ENV:Body>
        <LanguageCount xmlns="http://tempuri.org/">
          <fooAppID xsi:type="xsd:string">12345678-1234-1234-1234-123456789123</fooAppID>
          <sessionID xsi:type="xsd:string">12345678-1234-1234-1234-123456789123</sessionID>
        </LanguageCount>
      </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试在控制台中这样做时:

ruby-1.8.7-p302 > client = Savon::Client.new do |wsdl, http, wsse|
ruby-1.8.7-p302 >       wsdl.document = "http://FooService.cloudapp.net/FooService.svc?wsdl"
ruby-1.8.7-p302 ?>  end
 => #<Savon::Client:0x1055e2dc8 @http=#<HTTPI::Request:0x1055e2bc0>, @wsse=#<Savon::WSSE:0x1055e2b98>, @wsdl=#<Savon::WSDL::Document:0x1055e2c10 @request=#<HTTPI::Request:0x1055e2bc0>, @document="http://FooService.cloudapp.net/FooService.svc?wsdl">> 
ruby-1.8.7-p302 > 
ruby-1.8.7-p302 >   client.request :language_count, :body => {:Foo_app_id => "12345678-1234-1234-1234-123456789123", :session_id => "12345678-1234-1234-1234-123456789123"}
Retrieving WSDL from: http://FooService.cloudapp.net/FooService.svc?wsdl
HTTPI executes HTTP GET using the net_http adapter
SOAP request: http://Fooservice.cloudapp.net/FooService.svc
SOAPAction: "LanguageCount", Content-Type: text/xml;charset=UTF-8
<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:wsdl="http://tempuri.org/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"><env:Body><LanguageCount><FooAppId>12345678-1234-1234-1234-123456789123</FooAppId><sessionId>12345678-1234-1234-1234-123456789123</sessionId></LanguageCount></env:Body></env:Envelope>
HTTPI executes HTTP POST using the net_http adapter
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 'LanguageCount' 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></s:Envelope>
Savon::SOAP::Fault: (a:ActionNotSupported) The message with Action 'LanguageCount' 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).
Run Code Online (Sandbox Code Playgroud)

但是当我使用foo_web_service的命名空间时,我得到:

 ruby-1.8.7-p302 > client = Savon::Client.new do |wsdl, http, wsse| ruby-1.8.7-p302 >       wsdl.document = "http://FooService.cloudapp.net/FooService.svc?wsdl" ruby-1.8.7-p302 ?>  end  =>
#<Savon::Client:0x105882498 @http=#<HTTPI::Request:0x105882358>, @wsse=#<Savon::WSSE:0x105882330>, @wsdl=#<Savon::WSDL::Document:0x105882380 @request=#<HTTPI::Request:0x105882358>, @document="http://FooService.cloudapp.net/FooService.svc?wsdl">> ruby-1.8.7-p302 >  ruby-1.8.7-p302 >   client.request :Foo_web_service, :language_count, :body => {:Foo_app_id
=> "12345678-1234-1234-1234-123456789123", :session_id => "12345678-1234-1234-1234-123456789123"} Retrieving WSDL from: http://FooService.cloudapp.net/FooService.svc?wsdl HTTPI executes HTTP GET using the net_http adapter SOAP request: http://Fooservice.cloudapp.net/FooService.svc SOAPAction: "http://tempuri.org/FooService/LanguageCount", Content-Type: text/xml;charset=UTF-8 <?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:Foo_web_service="http://tempuri.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"><env:Body><Foo_web_service:LanguageCount><FooAppId>12345678-1234-1234-1234-123456789123</FooAppId><sessionId>12345678-1234-1234-1234-123456789123</sessionId></Foo_web_service:LanguageCount></env:Body></env:Envelope> HTTPI executes HTTP POST using the net_http adapter SOAP response (status 200): <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><LanguageCountResponse xmlns="http://tempuri.org/"><LanguageCountResult>-1</LanguageCountResult></LanguageCountResponse></s:Body></s:Envelope>
=> #<Savon::SOAP::Response:0x105a2cca8 @http=#<HTTPI::Response:0x105a28ce8 @body="<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body><LanguageCountResponse xmlns=\"http://tempuri.org/\"><LanguageCountResult>-1</LanguageCountResult></LanguageCountResponse></s:Body></s:Envelope>", @raw_body="<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body><LanguageCountResponse xmlns=\"http://tempuri.org/\"><LanguageCountResult>-1</LanguageCountResult></LanguageCountResponse></s:Body></s:Envelope>", @code=200, @headers={"x-powered-by"=>"ASP.NET", "x-aspnet-version"=>"4.0.30319", "content-type"=>"text/xml; charset=utf-8", "date"=>"Sat, 02 Jul 2011 23:40:56 GMT", "server"=>"Microsoft-IIS/7.0", "content-length"=>"214", "cache-control"=>"private"}>, @soap_fault=Savon::SOAP::Fault, @http_error=Savon::HTTP::Error>  ruby-1.8.7-p302 >
Run Code Online (Sandbox Code Playgroud)

Zac*_*lis 7

长话短说,我不得不进行3次更改.

  1. 改变response = client.request :language_countresponse = client.request "LanguageCount"
  2. 添加:xmlns => "http://tempuri.org/"到client.request调用的末尾
  3. 明确地称为SOAPaction,如: client.http.headers["SOAPAction"] = '"http://tempuri.org/FooService/LanguageCount"'

希望这可以帮助别人,因为我周末一直在SOAP地狱,希望我会阻止其他人在那里.