:-$

Ryan's work blog

My Links

News

The WeatherPixie
Subscribe with Bloglines
About this blog

Tools I use:

Post Categories

Article Categories

Archives

Image Galleries

Blog Stats

Personal

Projects

Random Blogs

Random other

Reference

Web comics

Work

Calling .NET web services with XUL

We're starting to use XUL to make nice interfaces, and encountered a bitch of a problem getting our javascript code running on the client to talk nicely with our .NET web services. The good folks at Mandragor & Apinc posted some really great content about creating applications with Mozilla, with a chapter on remote applications. That has a section on using javascript to call .NET web services. I thought "Great, thats precisely what I want to do, and here's a code sample." Unfortunately, the law of code samples off the web (sample code will never work, ever) still applied.

When the javascript sent the SOAP request, it's XML was formatted ever so differently, and the web service didn't like it. The web method would get called, but no data would be passed in. It was fun to see my breakpoint being hit for the first time, but quite disheartening to see every input was 0 or null. Some snippets:

Here's the bad javascript code (simplified a little for clarity) that generated the bad XML:
  ...
  //code from the tutorial
  var params  = new Array(
                  new SOAPParameter(this.contactId,"contactId"),
                  new SOAPParameter(this.comments,"comments")
                );
  //rest of the call from the tutorial
  ...
After looking at some of the documentation on the SOAPCall object, this all made reasonable sense. I thought having the SOAPParamter constructor take value before name was an odd choice, but whatever. Here's the generated XML:
   
   ...
    <a0:AddComment xmlns:a0="uri:Comment">
      <contactId>2</contactId>
      <comments>this is my comment</comments>
    </a0:AddComment>
  ...
We thought the "a0" business was a little odd, but figured the purpose of these SOAP objects was to abstract out those details and just do it right. So we spent a day of trying different meaningless tweaks, finding new debugging tools, cursing, and reading endless articles on XUL web services objects, WSDL, HTC, RDF, and god knows what else. Finally, we figured it out. The problem was with the SOAPParameters, and that little "a0" was the culprit. The SOAPParameter has a namespaceURI property that had to be set as well. After adding a helper function, here's the corrected code:
   function getParam (value, name, namespaceURI){
      var parm = new SOAPParameter(value, name);
      parm.namespaceURI = namespaceURI;
      return parm;
   }
   
  ...
  //code from the tutorial
  var params  = new Array(
                  getParam(this.contactId,"contactId", "uri:Comment"),
                  getParam(this.comments,"comments", "uri:Comment")
                );
  //rest of the call from the tutorial  
  ...
Now the generated XML has all the namespaces fixed:
   ...
    <a0:AddComment xmlns:a0="uri:Comment">
      <a0:contactId>2</a0:contactId>
      <a0:comments>this is my comment</a0:comments>
    </a0:AddComment>
  ...
The a0s make all the difference, and now it all works perfectly. As a bonus, we found some excellent tools:
  • LiveHTTPHeaders - Firefox plugin to view HTTP headers for requests and reponses.
  • Venkman - Javascript debugger for Mozilla based browsers, letting you step through code, etc.
  • XulRef - Firefox plugin to display a XUL reference in the sidebar, with links to the documentation.

posted on Friday, September 17, 2004 4:04 PM