Consuming Python Web Services with C#

Consuming Python Web Services written and deployed with Soaplib is possible using C# and Mono. I haven't try on .Net yet but if it works on Mono it definitively will work on .Net. You can read about Soaplib in previous posts.
First of all, write a web service that returns a single string and another that returns an array of strings:

  2. @soapmethod(String, _returns=String)
  3. def srv_getServerData(self, serverName):
  4. return str(Server.objects.filter(nombre=serverName).values())
  6. @soapmethod(_returns=Array(String))
  7. def srv_getServersList(self):
  8. results = []
  9. for servicesValues in Service.objects.values():
  10. results.append(str(servicesValues))
  11. return results

Second: Run the web server and generate the WSDL file. I do that using a Python client.

  2. def getWSDL():
  3. wsdl = getClientInfoService().server.wsdl("https://" +
  4. Server.getServerPublicIp() + ':' +
  5. constants.webServicesPort + constants.serviceUrl)
  6. fileName = '/tmp/service.wsdl'
  7. wsdlFile = open(fileName, 'w')
  8. wsdlFile.write(wsdl)
  9. wsdlFile.close()
  10. print "File generated:", '/tmp/service.wsdl'

Third: Generate the C# proxy reading the WSDL. We need the wsdl tool (package mono-1.0-devel on Ubuntu).
wsdl service.wsdl
That will create the file Service.cs. In this file there are several typecasts that are not working properly. In order to get the data from the service I modify it using sed.

  2. sed 's/return ((.*Response)(results\[0\]))/return ((System.Xml.XmlNode)results\[0\])/g' Service.cs > tmp1
  3. sed 's/public srv_.*Response/public System.Xml.XmlNode/g' tmp1 > Service.cs

Note that my services methods start with the "srv_" prefix, so I use that in the regex above to match them.
Fourth: C# code to get that from the services:

  2. // method 1:
  3. srv_getServerData y = new srv_getServerData();
  4. y.serverName = "pepino";
  5. Service client = new Service();
  6. System.Xml.XmlNode res = client.srv_getServerData(y).ChildNodes[0];
  7. String result = String.Empty;
  8. result = res.InnerText;
  10. // method 2:
  11. Service client = new Service();
  12. srv_getServersList x = new srv_getServersList();
  13. System.Xml.XmlNodeList result = client.srv_getServersList(x).ChildNodes;
  14. String result = String.Empty;
  15. foreach (System.Xml.XmlNode n in result)
  16. result += '\n' + n.InnerText;

It works!!!

NUnit on Mono: TypeLoadException

MonoDevelop 1.0 is available for Ubuntu 8.04, that is great news!. Mono 1.2.6 is the current version for this distro too. MonoDevelop 1.0 is 100 times more stable than 0.14 and it makes me feel productive now. It almost does not crash, the gui layout is very nice and the autocompletion works pretty well. I discarded OpenSuse eventually because it is sooooo slow, soooo heavy. By the way, Ubuntu Hardy works very well on my desktop computer but it makes my laptop crash very often :-(.
Mono community seems very small to me. I'd say people is using Mono to run their .Net apps on Linux but I don't see many people developing on Mono directly. Its development is in progress though, so good news again.

The tougher problem I've found so far is that NUnit wasn't working right. One of my unit tests is loading an assembly using Assembly.Load and then trying to get its types with assembly.GetTypes() and NUnit was throwing TypeLoadException. The solution has been to download NUnit 2.4.8 from the web, unzip it, change the nunit-console.exe.config to set encoding=utf-8 in the first line, and copy all the files under the bin folder to /usr/lib/nunit/. It is working fine, the test works.

The other problem is that adding an App.config file to my project makes gmcs (mono compiler) fail with "Parsing error". I have no clue, what's going on here?.