Ruby Savon 2 gem: 无法指定 XML 子元素和子元素向 SOAP API Web 服务发出有效请求
Ruby Savon 2 gem: cannot specify XML child and sub-child elements to make valid request to SOAP API Webservice
已经进行了大量的谷歌搜索并查看了 Savon 2 文档,但我认为我没有在我的 ruby 代码中正确指定 XML 子元素和子元素我需要 运行 成功请求此 SOAP 网络服务。
在 main2.rb 中,我尝试使用方括号语法将文档从 BookReservationRequest 到 Booker 再到 UserWithoutALogin。 (这种方括号方法在响应端的另一个示例中起作用)。不知何故,当我在 SOAP UI 中删除这些标签时,我没有在 Ruby 中正确指定这些标签,我得到了下面完全相同的错误消息。 (N.B 我对 Ruby 还是很陌生!)
完整错误跟踪:
ruby main2.rb
/Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/response.rb:85:in `raise_soap_and_http_errors!': (soap:Server) System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.NullReferenceException: Object reference not set to an instance of an object. (Savon::SOAPFault)
at Services.Internal.Helpers.CustomerHelper.GetCustomerIdFromGuestOrBookerType(Nullable`1 partnerServiceId, GuestOrBookerType guestOrBookerType) in c:\TeamCity\LB-QA-04\work\e2ec20c745b940f9\Source\Services\Internal\Helpers\CustomerHelper.cs:line 64
at Services.Internal.Service.BookReservation(BookReservationRequest bookReservationRequest) in c:\TeamCity\LB-QA-04\work\e2ec20c745b940f9\Source\Services\Internal\Service.asmx.cs:line 289
--- End of inner exception stack trace ---
from /Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/response.rb:14:in `initialize'
from /Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/operation.rb:72:in `new'
from /Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/operation.rb:72:in `create_response'
from /Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/operation.rb:58:in `call'
from /Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/client.rb:36:in `call'
from main2.rb:11:in `core_info'
from main2.rb:23:in `<main>'
Ruby代码(main2.rb):
require 'savon'
class BookReservation
def client
client = Savon.client(wsdl: "http://some-example-soap-wsdl-link", follow_redirects: :follow_redirects)
end
def core_info(partner_code, restaurant_location_id, session_id, dining_date_and_time, size)
message = { 'PartnerCode' => partner_code, 'RestaurantLocationId' => restaurant_location_id, 'SessionId' => session_id, 'DiningDateAndTime' => dining_date_and_time, 'Size' => size }
response = client.call(:book_reservation, message: message)
response.hash[:book_reservation_response]
end
def booker_info(first_name, last_name, email, guest_accepts_email_marketing)
message = { 'FirstName' => first_name, 'LastName' => last_name, 'EMail' => email, 'GuestAcceptsEmailMarketingFromPartner' => guest_accepts_email_marketing }
response = client.call([:book_reservation][:booker][:user_without_a_login], message: message)
response.body[:book_reservation_response]
end
end
book = BookReservation.new
puts book.core_info("DEV-DAN-BETH:73411", "10799", "DINNER", "2015-06-20T21:00:00", "2", )
puts book.booker_info("John", "Smith", "john.smith@example.com", "true")
Soap 中的这个 xml 文档UI returns 每次都是有效/成功的响应:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://schemas.livebookings.net/OneFormat/Aggregator/Internal/1/0/">
<soapenv:Header/>
<soapenv:Body>
<ns:BookReservationRequest>
<ns:PartnerCode>DEV-DAN-BETH:73411</ns:PartnerCode>
<ns:RestaurantLocationId>10799</ns:RestaurantLocationId>
<ns:SessionId>DINNER</ns:SessionId>
<ns:DiningDateAndTime>2015-06-20T21:00:00</ns:DiningDateAndTime>
<ns:Size>2</ns:Size>
<ns:Booker>
<ns:UserWithoutALogin>
<ns:FirstName>John</ns:FirstName>
<ns:LastName>Smith</ns:LastName>
<ns:EMail>john.smith@example.com</ns:EMail>
<ns:GuestAcceptsEmailMarketingFromPartner>true</ns:GuestAcceptsEmailMarketingFromPartner>
</ns:UserWithoutALogin>
</ns:Booker>
</ns:BookReservationRequest>
</soapenv:Body>
</soapenv:Envelope>
Soap 中成功响应的示例UI:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<BookReservationResponse xmlns="http://schemas.livebookings.net/OneFormat/Aggregator/Internal/1/0/">
<ConfirmationNumber>T2NVGBUN</ConfirmationNumber>
<ReservationId>34277666</ReservationId>
<AllowedToCancelOnline>true</AllowedToCancelOnline>
</BookReservationResponse>
</soap:Body>
</soap:Envelope>
非常感谢!
您的 SOAP 消息示例包含一个正文,该正文包含一个包含 Booker 块的图书预订请求。
您的 BookReservation
class 但是,包含两个调用 Savon 客户端的方法 - 其中一个发送 BookReservationRequest
- 但您之前从未将 Booker 添加到消息哈希派送中。
几乎可以 100% 确定您的客户端正在发送无效的 SOAP 请求,因为您没有在 SOAP 正文中指定 <ns:Booker>
块。
我怀疑如果您更新 class 以包含如下所示的一种方法:
def execute(partner_code, restaurant_location_id, session_id, dining_date_and_time, size, first_name, last_name, email, guest_accepts_email_marketing)
message = { 'PartnerCode' => partner_code, 'RestaurantLocationId' => restaurant_location_id, 'SessionId' => session_id, 'DiningDateAndTime' => dining_date_and_time, 'Size' => size }
message.merge!('Booker' => { 'FirstName' => first_name, 'LastName' => last_name, 'EMail' => email, 'GuestAcceptsEmailMarketingFromPartner' => guest_accepts_email_marketing })
response = client.call(:book_reservation, message: message)
response.hash[:book_reservation_response]
结束
并调用它:
book.execute(
"DEV-DAN-BETH:73411", "10799", "DINNER", "2015-06-20T21:00:00", "2",
"John", "Smith", "john.smith@example.com", "true" )
你的运气会更好。
已经进行了大量的谷歌搜索并查看了 Savon 2 文档,但我认为我没有在我的 ruby 代码中正确指定 XML 子元素和子元素我需要 运行 成功请求此 SOAP 网络服务。
在 main2.rb 中,我尝试使用方括号语法将文档从 BookReservationRequest 到 Booker 再到 UserWithoutALogin。 (这种方括号方法在响应端的另一个示例中起作用)。不知何故,当我在 SOAP UI 中删除这些标签时,我没有在 Ruby 中正确指定这些标签,我得到了下面完全相同的错误消息。 (N.B 我对 Ruby 还是很陌生!)
完整错误跟踪:
ruby main2.rb
/Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/response.rb:85:in `raise_soap_and_http_errors!': (soap:Server) System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.NullReferenceException: Object reference not set to an instance of an object. (Savon::SOAPFault)
at Services.Internal.Helpers.CustomerHelper.GetCustomerIdFromGuestOrBookerType(Nullable`1 partnerServiceId, GuestOrBookerType guestOrBookerType) in c:\TeamCity\LB-QA-04\work\e2ec20c745b940f9\Source\Services\Internal\Helpers\CustomerHelper.cs:line 64
at Services.Internal.Service.BookReservation(BookReservationRequest bookReservationRequest) in c:\TeamCity\LB-QA-04\work\e2ec20c745b940f9\Source\Services\Internal\Service.asmx.cs:line 289
--- End of inner exception stack trace ---
from /Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/response.rb:14:in `initialize'
from /Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/operation.rb:72:in `new'
from /Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/operation.rb:72:in `create_response'
from /Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/operation.rb:58:in `call'
from /Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/client.rb:36:in `call'
from main2.rb:11:in `core_info'
from main2.rb:23:in `<main>'
Ruby代码(main2.rb):
require 'savon'
class BookReservation
def client
client = Savon.client(wsdl: "http://some-example-soap-wsdl-link", follow_redirects: :follow_redirects)
end
def core_info(partner_code, restaurant_location_id, session_id, dining_date_and_time, size)
message = { 'PartnerCode' => partner_code, 'RestaurantLocationId' => restaurant_location_id, 'SessionId' => session_id, 'DiningDateAndTime' => dining_date_and_time, 'Size' => size }
response = client.call(:book_reservation, message: message)
response.hash[:book_reservation_response]
end
def booker_info(first_name, last_name, email, guest_accepts_email_marketing)
message = { 'FirstName' => first_name, 'LastName' => last_name, 'EMail' => email, 'GuestAcceptsEmailMarketingFromPartner' => guest_accepts_email_marketing }
response = client.call([:book_reservation][:booker][:user_without_a_login], message: message)
response.body[:book_reservation_response]
end
end
book = BookReservation.new
puts book.core_info("DEV-DAN-BETH:73411", "10799", "DINNER", "2015-06-20T21:00:00", "2", )
puts book.booker_info("John", "Smith", "john.smith@example.com", "true")
Soap 中的这个 xml 文档UI returns 每次都是有效/成功的响应:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://schemas.livebookings.net/OneFormat/Aggregator/Internal/1/0/">
<soapenv:Header/>
<soapenv:Body>
<ns:BookReservationRequest>
<ns:PartnerCode>DEV-DAN-BETH:73411</ns:PartnerCode>
<ns:RestaurantLocationId>10799</ns:RestaurantLocationId>
<ns:SessionId>DINNER</ns:SessionId>
<ns:DiningDateAndTime>2015-06-20T21:00:00</ns:DiningDateAndTime>
<ns:Size>2</ns:Size>
<ns:Booker>
<ns:UserWithoutALogin>
<ns:FirstName>John</ns:FirstName>
<ns:LastName>Smith</ns:LastName>
<ns:EMail>john.smith@example.com</ns:EMail>
<ns:GuestAcceptsEmailMarketingFromPartner>true</ns:GuestAcceptsEmailMarketingFromPartner>
</ns:UserWithoutALogin>
</ns:Booker>
</ns:BookReservationRequest>
</soapenv:Body>
</soapenv:Envelope>
Soap 中成功响应的示例UI:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<BookReservationResponse xmlns="http://schemas.livebookings.net/OneFormat/Aggregator/Internal/1/0/">
<ConfirmationNumber>T2NVGBUN</ConfirmationNumber>
<ReservationId>34277666</ReservationId>
<AllowedToCancelOnline>true</AllowedToCancelOnline>
</BookReservationResponse>
</soap:Body>
</soap:Envelope>
非常感谢!
您的 SOAP 消息示例包含一个正文,该正文包含一个包含 Booker 块的图书预订请求。
您的 BookReservation
class 但是,包含两个调用 Savon 客户端的方法 - 其中一个发送 BookReservationRequest
- 但您之前从未将 Booker 添加到消息哈希派送中。
几乎可以 100% 确定您的客户端正在发送无效的 SOAP 请求,因为您没有在 SOAP 正文中指定 <ns:Booker>
块。
我怀疑如果您更新 class 以包含如下所示的一种方法:
def execute(partner_code, restaurant_location_id, session_id, dining_date_and_time, size, first_name, last_name, email, guest_accepts_email_marketing)
message = { 'PartnerCode' => partner_code, 'RestaurantLocationId' => restaurant_location_id, 'SessionId' => session_id, 'DiningDateAndTime' => dining_date_and_time, 'Size' => size }
message.merge!('Booker' => { 'FirstName' => first_name, 'LastName' => last_name, 'EMail' => email, 'GuestAcceptsEmailMarketingFromPartner' => guest_accepts_email_marketing })
response = client.call(:book_reservation, message: message)
response.hash[:book_reservation_response]
结束
并调用它:
book.execute(
"DEV-DAN-BETH:73411", "10799", "DINNER", "2015-06-20T21:00:00", "2",
"John", "Smith", "john.smith@example.com", "true" )
你的运气会更好。