19th
MAY

Calling web services from JavaScript

Posted by radekg under Ajax

Recently I’ve started new research ASP.NET project, mainly to get up to speed with C# and learn best practices on Microsoft platform. One of the requirements is to build the web services API and use it to feed application interface. This would allow me to replace one interface with another (Silverlight or Flex) without modifying back end code. For the first interface I’ve chosen JavaScript (ExtJS library). First problem I found was: how to call and get web service result from JavaScript? Short googling for “web service JavaScript” brought some results, unfortunately none of existing solutions seem to work as Flex web services works.

In Flex I had to create WebService instance and pass WSDL URL to it. WebService object resolves WSDL and creates methods for matching operations. When web service operation is called it returns AsyncToken instance which is then used to get result or fault. Everything works asynchronously.

I managed to get that working in JavaScript and I’m sharing this here as some people may find this useful. This solution was tested on ASMX web services only. To use it, following files must be loaded to HTML document:

  • js/rpc/soap/AsyncToken.js
  • js/rpc/soap/WebService.js
  • js/rpc/soap/WebServiceConstants.js
  • js/rpc/soap/WebServiceOperation.js
  • js/rpc/soap/WebServiceUtils.js

To use it all that have to be done is:

function onPageLoaded() {
var ws = new WebService( "http://localhost/test.asmx" );
ws.resolve( onResolved, "?wsdl" );
}function onResolved( sender ) {
var token = sender.TestOperation.call( { param1: "some param" } );
token.addResponder( new TestOperationResponder() );
}

onPageLoaded() function is called by <body onload=”"> and it is executed when all JS files are loaded. WebService constructor takes web service URL as a parameter. Next step is to call resolve() method. This method loads WSDL file and based on its contents generates operations on WebService instance. resolve() takes two parameters, both of them are optional. First one is listener function, called when WSDL is loaded and parsed, second one is the string that has to be appended in order to resolve WSDL file. So in above sample http://localhost/test.asmx is the URL where data is posted and http://localhost/test.asmx?wsdl is WSDL definition URL.

onResolved() method will be executed only when WSDL is correctly loaded. sender argument is the instance of WebService which executed this handler. onResolved() method shows how to execute operation on web service. Simply do ws.operation.call() and pass arguments as object with keys matching operation arguments and values matching argument values. When call() method is executed AsyncToken instance is returned. To get access to result or fault “token responder” must be registered on token. Sample responder may look like this:

TestOperationResponder = function() {}
TestOperationResponder.prototype.result = function( sender, data ) {
alert("Response from operation " + sender.getName() +
", service: " + sender.getService().getName() + " : + data );
}

TestOperationResponder.prototype.fault = function( sender, data ) {
alert("Fault from operation " + sender.getName() +
", service: " + sender.getService().getName() );
var _fault = "";
for (var key in data) { _fault += key + " : " + data[key]; }
alert(_fault);
}

This project isn’t complete and definitely should not be used “as is”. It is just a reference how web service may be handled from JavaScript. This code was tested on IE8 and Firefox 3 beta 5.

Because of cross URL limitations of XMLHttpRequest it may load web services only from the same host as HTML file was loaded.

Source code is available here.

Leave a Reply