{"id":20,"date":"2008-06-12T19:06:59","date_gmt":"2008-06-13T00:06:59","guid":{"rendered":"http:\/\/blog.monnet-usa.com\/?p=20"},"modified":"2009-07-24T21:18:25","modified_gmt":"2009-07-25T04:18:25","slug":"from-ruby-silverlight-to-ruby-web-service-with-a-touch-of-spice","status":"publish","type":"post","link":"https:\/\/blog.monnet-usa.com\/?p=20","title":{"rendered":"From Ruby Silverlight to Ruby Web Service (with a touch of spice)"},"content":{"rendered":"<p>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.<br \/>\nThe advantages such a scenario would bring include:<br \/>\n&#8211; increased developer productivity due to single end-to-end language experience<br \/>\n&#8211; greater leverage through the expressiveness and power of the Ruby language<br \/>\n&#8211; shorter cycle time due lack of compilation step (especially when running on the Silverlight-specific Chiron development web server)<br \/>\n&#8211; wider options in terms of class libraries, SDKs, and tools<\/p>\n<p>So let&#8217;s look at what is needed to make the Ruby &#8220;all-the-way&#8221; option work:<br \/>\n1. The ability to leverage traditional .NET assemblies from Ruby.<br \/>\n2. The Silverlight ServiceModel stack (a subset of WCF, right-sized for the client).<\/p>\n<p>IronRuby allows integration with the .NET platform &#8211; even using strongly-typed collections! Not bad for a dynamically typed language :-)  !!!<br \/>\nThe challenge is that the WCF approach requires the use of .NET attributes to &#8220;decorate&#8221; the contract definition.<\/p>\n<pre class=\"brush: csharp\">\r\n[System.ServiceModel.OperationContractAttribute\r\n(AsyncPattern=true, Action=\"\/ws_tst\/api\/GetTime\", ReplyAction=\"*\")]\r\n<\/pre>\n<p>Unfortunately IronRuby does not support that for the time being (still alpha).<br \/>\nSo the solution for now is to:<br \/>\n1. Generate and tweak the web service proxy in C#,<br \/>\n2. Package it up in a small assembly<br \/>\n3. Copy the assembly in the Silverlight .xap package to the Silverlight app folder.<br \/>\n4. Add the assembly declaration to the AppManifest.xaml<\/p>\n<p>[xaml]<br \/>\n[\/xaml<\/p>\n<p>Then, we can move on to the Silverlight client implementation:<br \/>\n1. Declare our web service proxy assembly and its namespaces<\/p>\n<pre class=\"brush: ruby\">\r\nrequire \"RorMonnetUsaComSoap\"\r\ninclude RorMonnetUsaComSoap\r\ninclude RorMonnetUsaComSoap::RoRServiceReference\r\n<\/pre>\n<p>2. Instantiate the WCF client generated for our web service port<\/p>\n<pre class=\"brush: ruby\">\r\n@svcproxy = WsTstWsTstPortClient.new()\r\n<\/pre>\n<p>3. Wire up an event handler for the asynchronous web service call (since Silverlight requires asynchronous calls)<\/p>\n<pre class=\"brush: ruby\">\r\n@svcproxy.GetTimeCompleted { |sender, args|  txtResults.text = args.result }\r\n<\/pre>\n<p>4. Wire up a button event handler to request the asynchronous web service call<\/p>\n<pre class=\"brush: ruby\">\r\nbtnTest.click { |sender, args| @svcproxy.GetTimeAsync() }\r\n<\/pre>\n<p>Summary:<\/p>\n<pre class=\"brush: ruby\">\r\nrequire \"Silverlight\"\r\nrequire \"System\"\r\nrequire \"System.ServiceModel\"\r\n\r\nrequire \"RorMonnetUsaComSoap\"\r\n\r\ninclude System\r\ninclude System::Net\r\ninclude System::ServiceModel\r\n\r\ninclude RorMonnetUsaComSoap\r\n\r\nclass App &lt; SilverlightApplication\r\nuse_xaml\r\n\r\ndef initialize\r\n\r\n@svcproxy = initializeServiceProxy()\r\n\r\n# wire up web service callback\r\n@svcproxy.GetTimeCompleted { |sender, args| handle_get_time_completed(sender, args) }\r\n\r\n# wire up the button handler\r\nbtnTest.click { |sender, args| handle_btn_clicked(sender, args) }\r\n\r\nend #initialize method\r\n\r\ndef initializeServiceProxy\r\ntxtResults.text = \"Initializing the svc proxy ...\"\r\nproxy = RorMonnetUsaComSoap::RoRServiceReference::WsTstWsTstPortClient.new()\r\ntxtResults.text = \"proxy initialized! ready!\"\r\nreturn proxy\r\nend\r\n\r\ndef handle_btn_clicked(sender, args)\r\ntxtResults.text = \"Ready to invoke the service ...\"\r\n@svcproxy.GetTimeAsync();\r\ntxtResults.text = \"Going ...\"\r\nend\r\n\r\ndef handle_get_time_completed(sender, args)\r\ntxtResults.text = \"Done! [\" + args.result.to_s + \"]\"\r\nend\r\n\r\nend # App class\r\n\r\nApp.new\r\n<\/pre>\n<p>Et Voil\u00c3 !<\/p>\n<p><a id=\"p21\" class=\"imagelink\" title=\"slir2rorws.Png\" rel=\"attachment\" href=\"https:\/\/blog.monnet-usa.com\/?attachment_id=21\"><img decoding=\"async\" id=\"image21\" src=\"https:\/\/blog.monnet-usa.com\/wp-content\/uploads\/2008\/06\/slir2rorws.Png\" alt=\"slir2rorws.Png\" \/><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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: &#8211; increased developer productivity due to single end-to-end language experience &#8211; greater leverage through the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,7],"tags":[],"class_list":["post-20","post","type-post","status-publish","format-standard","hentry","category-ruby","category-silverlight"],"_links":{"self":[{"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=\/wp\/v2\/posts\/20","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=20"}],"version-history":[{"count":3,"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=\/wp\/v2\/posts\/20\/revisions"}],"predecessor-version":[{"id":152,"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=\/wp\/v2\/posts\/20\/revisions\/152"}],"wp:attachment":[{"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=20"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=20"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.monnet-usa.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=20"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}