From Ruby Silverlight to Ruby Web Service (with a touch of spice)
After validating I could create a C# Silverlight client calling both document-style SOAP .net web service and an RPC-style SOAP Rails web service, it was time to move to the all-in-Ruby scenario.
The advantages such a scenario would bring include:
– increased developer productivity due to single end-to-end language experience
– greater leverage through the expressiveness and power of the Ruby language
– shorter cycle time due lack of compilation step (especially when running on the Silverlight-specific Chiron development web server)
– wider options in terms of class libraries, SDKs, and tools
So let’s look at what is needed to make the Ruby “all-the-way” option work:
1. The ability to leverage traditional .NET assemblies from Ruby.
2. The Silverlight ServiceModel stack (a subset of WCF, right-sized for the client).
IronRuby allows integration with the .NET platform – even using strongly-typed collections! Not bad for a dynamically typed language :-) !!!
The challenge is that the WCF approach requires the use of .NET attributes to “decorate” the contract definition.
[System.ServiceModel.OperationContractAttribute (AsyncPattern=true, Action="/ws_tst/api/GetTime", ReplyAction="*")]
Unfortunately IronRuby does not support that for the time being (still alpha).
So the solution for now is to:
1. Generate and tweak the web service proxy in C#,
2. Package it up in a small assembly
3. Copy the assembly in the Silverlight .xap package to the Silverlight app folder.
4. Add the assembly declaration to the AppManifest.xaml
[xaml]
[/xaml
Then, we can move on to the Silverlight client implementation:
1. Declare our web service proxy assembly and its namespaces
require "RorMonnetUsaComSoap" include RorMonnetUsaComSoap include RorMonnetUsaComSoap::RoRServiceReference
2. Instantiate the WCF client generated for our web service port
@svcproxy = WsTstWsTstPortClient.new()
3. Wire up an event handler for the asynchronous web service call (since Silverlight requires asynchronous calls)
@svcproxy.GetTimeCompleted { |sender, args| txtResults.text = args.result }
4. Wire up a button event handler to request the asynchronous web service call
btnTest.click { |sender, args| @svcproxy.GetTimeAsync() }
Summary:
require "Silverlight" require "System" require "System.ServiceModel" require "RorMonnetUsaComSoap" include System include System::Net include System::ServiceModel include RorMonnetUsaComSoap class App < SilverlightApplication use_xaml def initialize @svcproxy = initializeServiceProxy() # wire up web service callback @svcproxy.GetTimeCompleted { |sender, args| handle_get_time_completed(sender, args) } # wire up the button handler btnTest.click { |sender, args| handle_btn_clicked(sender, args) } end #initialize method def initializeServiceProxy txtResults.text = "Initializing the svc proxy ..." proxy = RorMonnetUsaComSoap::RoRServiceReference::WsTstWsTstPortClient.new() txtResults.text = "proxy initialized! ready!" return proxy end def handle_btn_clicked(sender, args) txtResults.text = "Ready to invoke the service ..." @svcproxy.GetTimeAsync(); txtResults.text = "Going ..." end def handle_get_time_completed(sender, args) txtResults.text = "Done! [" + args.result.to_s + "]" end end # App class App.new
Et VoilĂ !