SOAP, .Net, Ruby

Using SOAP with Ruby is classic… someone spent a ton of time writing some great code and documented via google groups question and answer threads to ensure you enjoyed the maximum amount of frustration using their code. Hopefully this will clear things up for someone.

We want to call a relatively simple ASP.NET webservice OrderStatus.asmx. It has nested inputs, which makes most of the examples you find for this kind of thing useless.


POST /ext/OrderStatusWithItems/OrderStatus.asmx HTTP/1.1

Host: www.ioperate.net

Content-Type: text/xml; charset=utf-8

Content-Length: length

SOAPAction: "http://ioperate.net/ws/GetStatus"



<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">

  <soap:Body>

    <GetStatus xmlns="http://ioperate.net/ws/">

      <pVendorInformation>

        <VendorCode>string</VendorCode>

        <VendorKey>string</VendorKey>

      </pVendorInformation>

      <pOrderNumber>string</pOrderNumber>

      <Mode>int</Mode>

    </GetStatus>

  </soap:Body>

</soap:Envelope>



First: install soap4r

> sudo gem install soap4r

Second: change boot.rb in Rails

You need to add the gem in boot.rb for any of this to work. Below “require ‘rubygems'” put “require_gem ‘soap4r'”

Third: generate code

In your rails project…

> cd lib
> wsdl2ruby.rb --wsdl http://www.ioperate.net/ext/OrderStatusWithItems/OrderStatus.asmx?WSDL --type client --force --classdef OrderStatus

Most .net webservices have a link to the wsdl definition

This will generate OrderStatus.rb, OrderStatusClient.rb, OrderStatusDriver.rb, OrderStatusMappingRegistry.rb

Fourth: code up the call

In any controller you’d call it like so….


#sample call... note, since these vendor info is fake this won't work - but it demonstrates how to make complex SOAP calls from ruby

def wstest

  require 'OrderStatusDriver.rb'

  oss = OrderStatusSoap.new

  

  #oss.getStatus call requires the GetStatus object defined in OrderStatus.rb which requires the VendorInfo object

  vi = VendorInfo.new("abc", "aavvccdd") #note - this will fail since this isn't a valid login

  gs = GetStatus.new(vi,"419",1)  #pass in vendor info order # of "419" and a mode of 1

  

  objGetStatusResult = oss.getStatus(gs)

  

  #note - it returns the object GetStatusResult defined in OrderStatus.rb

  #so you could do stuff like objGetStatusResult.getStatusResult.shipDate

  raise objGetStatusResult.to_yaml + "Ship Date:  " + objGetStatusResult.getStatusResult.shipDate

end