无法让Savon形成正确的XML

时间:2011-07-03 00:07:04

标签: 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客户端电话(<LanguageCount>)而不是Savon的电话(<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>

然而,当我尝试在控制台中这样做时:

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).

但是当我使用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 >

1 个答案:

答案 0 :(得分:7)

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

  1. response = client.request :language_count更改为 response = client.request "LanguageCount"
  2. 在client.request调用结束时添加了:xmlns => "http://tempuri.org/"
  3. 明确地称为SOAPaction,如:client.http.headers["SOAPAction"] = '"http://tempuri.org/FooService/LanguageCount"'
  4. 希望这可以帮助别人,因为我周末一直在使用SOAP地狱,希望我能阻止其他人在那里。