AJAX WebService Component
AJAX WebService Component

Overview
Download
License
Architecture
Tutorial
API
Support

WebService Explorer
WebService Explorer

Overview
Download
Online
License
Guide
Support

AJAX WebService  Component Tutorial

The AJAX WebService  Component tutorial provides detailed information how to use our component, based upon public WebService named "GeoIpService". This tutorial provides way to invoke this web service only with component calls, without stub code generation (this way also known as dynamic invocation).

Let's take a look to public web service named "GeoIpService"; it provides you way to find to which countries such IP address belongs to.

The exact WSDL data is available at the following URL:

http://www.webservicex.net/geoipservice.asmx?WSDL.

In addition to GeoIp service, and to demonstrate multiple web services invocation at one time, we also using Global Weather Service:

http://www.webservicex.net/globalweather.asmx?WSDL

The tutorial provides step-by-step description provides you information how to create simple and pure client-side application for GeoIpService service operations through AJAX WebService  Component.

Invoking WebService

At first, we'll provide simple way: without meta-information discovery and without other advanced features. And we does not provide information how to operate with RPC-style calls in comparison to document style calls and complex parameters. Please see advanced example how to understand where and why we need to work with these differences,

At first, you need to create your project (for example simple html file) on your local hard drive, and include "AJAX WebService  Component" files, like the following example:

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<!--Including "AJAX WebService  Component"  files - à

<script type="text/javascript" src="wsclient.js"></script>

<script type="text/javascript" src="wsdlinfo.js"></script>

<head>

<title>GeoIPService</title>

<script>

function doInvoke() {

var wsdlInfo = new WSDLInfo();

    var wsdlLocation = "http://www.webservicex.net/geoipservice.asmx?WSDL";

    var operation = null;

    var soapPortName = "GeoIPServiceSoap";

   // load wsdl and parse it

   var callback = function() {

        // then find GetGeoIP operation from service definition

        operation = wsdlInfo.findOperation ("GetGeoIP", soapPortName, "GeoIPService");  

        // Now we ready to fill  parameters

       var parameters = new WSClientParameters

       parameters.add("IPAddress", "1.2.3.4");

 

       // Invoke .

       var result = operation.invoke(parameters, false, null);

       var out_parts = operation.getOutput ().getMessage().getParts();

 

        // and collect response

        var resultString = '';

        for (var i = 0; i < out_parts.length; ++i) {

              resultString += \n' + out_parts[i].getName () + " = " + result[out_parts[i].getName()];

        alert(resultString);

   }

   wsdlInfo.loadWsdl(wsdlLocation, callback);

}

And by adding simple button

</script>

<body>

GetGeoIP Service: dumb example

<input type="button" value="Click me!" onClick="doInvoke()"/>

</body>

</html>

we have way to launch web service as much cases as we need. Sure, there is easy.

Accessing request/response parameters

Usually, you don't need to handle whole response structure yourself; in case you working with such scalar parameters and complex types without arrays, you able to prefer simple access by parameters' names. And AJAX WebService Component provides that way for you.

So, the invocation code can be written as

var GetCitiesByCountry = null;

var GLobalWeatherServiceInfo = new WSDLInfo ();

var globalcallback = function()

{

    GetCitiesByCountry = GLobalWeatherServiceInfo.findOperation ("GetCitiesByCountry", "GlobalWeatherHttpPost", "GlobalWeather");

    var GetCitiesByCountryParameters = GetCitiesByCountry.getInputParameterMap ();

    GetCitiesByCountryParameters.getParameters ()["CountryName"] = "Belgium";

    var finalResponse = GetCitiesByCountry.invoke(GetCitiesByCountryParameters, false, null);

    alert(finalResponse["GetCitiesByCountryResult"]);

}

GLobalWeatherServiceInfo.loadWsdl("http://www.webservicex.net/globalweather.asmx?WSDL", globalcallback);

 

It also easy, though.

So first example can be rewritten as

function doInvoke() {

    var wsdlInfo = new WSDLInfo ();

    var operation = null;

   // load wsdl and parse it

   var callback = function() {

       // then find GetGeoIP operation from service definition

       operation = wsdlInfo.findOperation ("GetGeoIP", "GeoIPServiceSoap", "GeoIPService");  

       var args = operation.getInputParameterMap ();

       args.getParameters ()["IPAddress"] = "1.2.3.4";

 

       // Invoke .

       var result = operation.invoke(args, false, null);

       var out_parts = operation.getOutput ().getMessage().getParts();

       alert(out_parts["CountryName"]);

   }

   wsdlInfo.loadWsdl("http://www.webservicex.net/geoipservice.asmx?WSDL", callback);

}

Both ways are accessible; and depending of your task you able to either use direct access by names, or navigate through whole response structure.

More complexity: Adding parameters

Now we ready to make more: incorporate into HTML and add parameters and such dynamics.

Step 1: Creating application skeleton

At first, you need to create your project (for example simple html file) on your local hard drive, and include "AJAX WebService  Component" files, like the following example:

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<!--Including "AJAX WebService  Component"  files - à

<script type="text/javascript" src="wsclient.js"></script>

<script type="text/javascript" src="wsdlinfo.js"></script>

<head>

<title>GeoIPService</title>

<!--Defining such styles for buttons and text fields -à

<style>

.buttonType {

       width:200px;

       background:#ffffff;

       color:#000000;

       border-bottom-width:1px;

       border-left-width:1px;

       border-right-width:1px;

       border-top-width:1px;

       border-color:black;

       border-width:2px;

}

.inputType {

    border-bottom-width:1px;

     border-bottom-width:1px;

     border-left-width:1px;

     border-right-width:1px;

     border-top-width:1px;

     border-color:#000000;

     width:200px;

}

</style>

</head>

<body>

.

</body>

</html>

Step 2: HTML layout

Now we ready to add more complexity: parameters and dynamic lookup for specific port type. We still don't need find many information; we apologizes you know what you want to invoke. If you need more information, please see other tutorial section with advanced example.

Now it is time to add some html elements to our page:

<body onload="getWsdlInformation()">

 <fieldset>

     <p><strong><legend>GeoIPService</legend></strong></p>

     <p>

     <input type="text" class="inputType" id="IPAddress" value="1.2.3.4"/>

     <br/>

     <input type="button" class="buttonType" onClick="doInvoke()"/>

     </p>

     <div id="response" width="200" height="100">.</div>

 </fieldset>

</body>

Step 3: Invoke  and retrieve response

And there is simple function invokes web service we skipped above:

<script type="text/javascript">

/**

 WSDLInfo  object that holds all information about current webservice

 */

var wsdlInfo = new WSDLInfo ();

/**

 Wsdl file location at  remote HTTP server

 */

var wsdlLocation = "http://www.webservicex.net/geoipservice.asmx?WSDL";

/**

 Holds operation from current wsdl we planning to use

 */

var operation = null;

/**

 Soap portType name for GeoIPService

 */

var soapPortName = "GeoIPServiceSoap"

/**

 Fuction to load wsdl from remote location and parse

 */

function getWsdlInformation()

{

    /**

      CallBack object will be invoked when WSDL parser finished his work

    */

   var callback = function() {

        operation = wsdlInfo.findOperation ("GetGeoIP", soapPortName, "GeoIPService");   class=Sources0> }

   // load wsdl and parse it

   wsdlInfo.loadWsdl(wsdlLocation, callback);

}

.

 

function doInvoke()

{

       var value = document.getElementById("IPAddress").value;

       var parameters = new WSClientParameters ();

       parameters.add("IPAddress",value);

 

       // Invoke .

       var result = operation.invoke(parameters, false, null);

        var out_parts = operation.getOutput ().getMessage().getParts();

 

        // and collect response

        document.getElementById("response").innerHTML =  out_parts["CountryName"];

}

</script>

As you can se, there are no much differences.

Calling Multiple WebServices

The following full example demonstrates how to use multiple WebServices in none script; and output of one WebService is being used as input parameters for another.

At first, we need to define JavaScript code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<!-- Including AJAX WebService Component files -->

<script type="text/javascript" src="wsclient.js"></script>

<script type="text/javascript" src="wsdlinfo.js"></script>

<script type="text/javascript">

/**

 WSDLInfo  object that holds all information about GeoIpWebService webservice

 */

var IpServiceInfo = new WSDLInfo ();

/**

 WSDLInfo  object that holds all information about Globalweather webservice

 */

var GLobalWeatherServiceInfo = new WSDLInfo ();

/**

 Wsdl(GeoIpWebService) file location at  remote HTTP server

 */

var ipServiceWsdlLocation = "http://www.webservicex.net/geoipservice.asmx?WSDL";

/**

 Wsdl(Globalweather) file location at  remote HTTP server

 */

var globalWeatherServiceWsdlLocation = "http://www.webservicex.net/globalweather.asmx?WSDL";

/**

 Holds SOAP service name

 */

var soapPortName = "GeoIPServiceSoap"

/**

 Holds SOAP service name

 */

var HttpPostPortName = "GlobalWeatherHttpPost"

/**

 Indicators (true if wsdl have been succsessfuly loaded)

 */

var isIpReady = false;

var isGlobalReady = false;

/**

 Object that holds "getGeoIPContext" operation

 */

var getGeoIPContextOperation = null;

/**

 Object that holds "GetCitiesByCountry" operation

 */

var GetCitiesByCountry = null;

/**

 Loading WSDLs

 */

function getWsdlInformation()

{

    /**

     CallBack object for GeoService will be invoked when WSDL parser finished his work

     */

    var ipcallback = function()

    {

        //Find "GetGeoIPContext" operation from  GeoIPService

        getGeoIPContextOperation = IpServiceInfo.findOperation (

            "GetGeoIPContext", soapPortName, "GeoIPService");

        if (isGlobalReady)

        {

            document.getElementById("InvokeButton").disabled = false;

            document.getElementById("Message").style.display = "none";

        }

        isIpReady = true;

    }

    /**

     CallBack object for GlobalWeather will be invoked when WSDL parser finished his work

     */

    var globalcallback = function()

    {

        /**Find "GetCitiesByCountry" operation from  GeoIPService */

        GetCitiesByCountry = GLobalWeatherServiceInfo.findOperation (

             "GetCitiesByCountry", HttpPostPortName, "GlobalWeather");

        if (isIpReady)

        {

            document.getElementById("InvokeButton").disabled = false;

            document.getElementById("Message").style.display = "none";

        }

        isGlobalReady = true;

    }

    /**LOADING WSDLS FROM REMOTE LOCATIONS*/

    IpServiceInfo.loadWsdl(ipServiceWsdlLocation, ipcallback);

    GLobalWeatherServiceInfo.loadWsdl(globalWeatherServiceWsdlLocation, globalcallback);

}

/**

 This function invokes webservice workflow

 */

function invokeFlow()

{

    document.getElementById("Tracking").value = "";

    // There is servant callback functionthat demonstrates how to operate with callbacks from WebService calls

    // Currently this function provides debugging output without any handling of tracked response.

    var tracking = function(node, type)

    {

        document.getElementById("Tracking").value += "\n\n" + type + "\n";

        document.getElementById("Tracking").value += node;

    }

    /** Get prepared input parameters */

    var getGeoIPContextOperationParameters = getGeoIPContextOperation.getInputParameterMap ();

    /** Get ip context(Country name) and paste getGeoIPContextOperationParameters(WSClientParameters) object.

        This service using SOAP port to submit request data to server.

     */

    var response = getGeoIPContextOperation.invoke(getGeoIPContextOperationParameters, false, tracking);

    /** Getting needed fields from response map */

    var currenCountryName = response["GetGeoIPContextResult"]["CountryName"];

    /** Get prepared input parameters */

    var GetCitiesByCountryParameters = GetCitiesByCountry.getInputParameterMap ();

    /** Fill request parameter*/

    GetCitiesByCountryParameters.getParameters ()["CountryName"] = currenCountryName;

    /** Invoke  "GetCitiesByCountry" operation and paste request parameter(WSClientParameters) object.

     This service using HTTP POST to submit data to server.

     With this code we demonstrating different invocation methods being supported.

     */

    var finalResponse = GetCitiesByCountry.invoke(GetCitiesByCountryParameters, false, tracking);

    document.getElementById("Result").value = finalResponse["GetCitiesByCountryResult"];

}

</script>

There are CSS definitions:

<head>

    <title>

        WorkFlow

    </title>

<head>

    <style type="text/css">

        .buttonType {

            width: 200px;

            background: #ffffff;

            color: #000000;

            border-color: black;

            border-width: 2px;

        }

        .inputType {

            border-bottom-width: 1px;

            border-left-width: 1px;

            border-right-width: 1px;

            border-top-width: 1px;

            border-color: #000000;

            width: 200px;

        }

        .resultType {

            border-bottom-width: 1px;

            border-left-width: 1px;

            border-right-width: 1px;

            border-top-width: 1px;

            border-color: #000000;

            width: 200px;

        }

        .trackType {

            border-bottom-width: 1px;

            border-left-width: 1px;

            border-right-width: 1px;

            border-top-width: 1px;

            border-color: #000000;

            width: 800px;

        }

    </style>

</head>

And the rest of document contains view of the example, including all required controls.

<body onload="getWsdlInformation()">

<fieldset>

    <strong>

        <legend>Webservices workflow sample application</legend>

    </strong>

    <br/>

    <strong><label id="Message"><font color="#ff0000">Loading WSDL.Please wait...</font></label></strong>

    <br>

    <input id="InvokeButton" type="button" value="Go!" class="buttonType" disabled onclick="invokeFlow()"/>

    <br/>

    <br/>

    <strong><label>Flow result</label></strong>

    <br/>

    <textarea rows="10" cols="20" class="resultType" readonly id="Result"></textarea>

    <br/>

    <br/>

    <strong><label>Tracking history</label></strong>

    <br/>

    <textarea rows="20" cols="20" class="trackType" readonly id="Tracking"></textarea>

    <br/>

    <br/>

</fieldset>

</body>

</html>

Complex example: all dynamically handled

Step 1: Creating application skeleton

At first, you need to create your project (for example simple html file) on your local hard drive, and include "AJAX WebService  Component" files, like the following example:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<!-- Including "AJAX WebService Component" files -->

<script type="text/javascript" src="wsclient.js"></script>

<script type="text/javascript" src="wsdlinfo.js"></script>

 

<head>

<title>GeoIPService</title>

<!--Defining such styles for buttons and text fields - à

<style type="text/css">

 .buttonType {

       width:200px;

       background:#ffffff;

       color:#000000;

       border-color:black;

       border-width:2px;

}

 .inputType {

     border-bottom-width:1px;

     border-left-width:1px;

     border-right-width:1px;

     border-top-width:1px;

     border-color:#000000;

     width:200px;

}

 .resultType {

     border-bottom-width:1px;

     border-left-width:1px;

     border-right-width:1px;

     border-top-width:1px;

     border-color:#000000;

     width:200px;

}

</style>

</head>

<body>

.

</body>

</html>

Step 2: Discover meta-information

 

To call web service, all that we have to know is WSDL file location. Now you need to write function for getting operations list from Soap port type; there is first step to discover meta-information from web service and call it.

Now it is time to add some html elements to our page:

<body onLoad="getWsdlInformation()">

     <fieldset>

     <p><strong><legend>GeoIPService</legend></strong></p>

     <div align="right">

          <strong>Select type : </strong>

          <select id="selectType" disabled style="width:200px" onchange="clearAll()" >

              <option value="false">Dynamic input creation</option>

              <option value="true">Static input creation</option>

          </select>&nbsp;&nbsp;&nbsp;<br/>

          <strong>Select operation : </strong>

          <select id="selectOperation" disabled style="width:200px"  onchange="createInputs()" ></select> &nbsp;&nbsp;&nbsp;

     </div>

    <br/>

    <br/>

    <br/>

    </fieldset>

    <div id="response" align="right" style="display:none; background:bisque">

    </div>

</body>

Now we have to include script section to our html file and declare global variables and functions:

<script type="text/javascript">

/**

 WSDLInfo  object that holds all information about current webservice

 */

var wsdlInfo = new WSDLInfo ();

/**

 Wsdl file location at  remote HTTP server

 */

var wsdlLocation = "http://www.webservicex.net/geoipservice.asmx?WSDL";

/**

 Holds all operations from current wsdl

 */

var operations = null;

/**

 Soap portType name for GeoIPService

 */

var soapPortName = "GeoIPServiceSoap"

/**

 Indicator (true if wsdl have been succsessfuly loaded)

 */

var isReady = false;

/**

 Fuction to load wsdl from remote location and parse

 */

function getWsdlInformation()

{

    /**

      CallBack object will be invoked when WSDL parser finished his work

    */

   var callback = function() {

        // get all WsdlServices from wsdl as Array

        var services = wsdlInfo.getServices ();

        for (var serviceIdx in services) {

             //get all WsdlPorts from wsdl as Array

             var ports = services[serviceIdx].getPorts ();

             for (var portIdx  in ports) {

                  // get WsdlPortType from current port

                  var types = ports[portIdx].getWsdlPortType ();

                  if (types.getName () == soapPortName) {

                       // retrive all operations from current PortType

                       operations = types.getOparations();

                  }

             }

        }

         //when wsdl parsing finished

         enableSelectBox();

   }

   // load wsdl and parse it

   wsdlInfo.loadWsdl(wsdlLocation, callback);

}

/**

 Fill operation select box

 */

function enableSelectBox()

{

     document.getElementById("selectType").disabled = false;

     var select = document.getElementById("selectOperation");

     var j = 0;

     for (var i in operations)

     {

           select.options[j] = new Option(operations[i].getName (), operations[i].getName());

           j++;

     }

     select.disabled = false;

}

</script>

As we defined above, "getWsdlInformation()" method will invoked immediately after loading page. As result, the combo box will be filled with all possible operations, as follows:

Step 3: Prepare parameters

Now we can continue to discover information from web services. So we need inputs to provide incoming parameters for operations. For doing this we will dynamically create html input fields. To do this we have to add little bit more functions:

 

/**

 Create inputs for current operation

 */

function createInputs()

{

   

    //get selected operation  from document selectbox

    var operationName = document.getElementById("selectOperation").value;

    document.getElementById('staticInput').innerHTML = "";

    document.getElementById('staticInput').style.display = "";

    fillRequest(operationName);

    /* else {

        // Create static fields: removed now

        // if you like this you'll need to either know proper parameter names, or provide

        // certain mapping between your parameter' names and web service parameter names.

        // The case you know parameter names is pretty simple and described in examples;

        // 2nd way is not so interesting for tutorial case.

        document.getElementById('staticInput').style.display = "none";

     }*/

}

/**

 Dynamicaly creates inputs for operations.

 It also adds invoke button at the end of input fields list

 Parameters: operation name

 */

function fillRequest(operationName)

{

    var operation;

    for (var i in operations)

          if (operations[i].getName () == operationName)

               operation = operations[i];

     if (operation) {

           var parametersString = '';

           document.getElementById('staticInput').innerHTML = getRequestInputs(parametersString) +

                 getHtmlButton('Invoke ');

      }

      else

           throw new Error("No operation found");

}

/**

   Getting all inputs for current operation.

   All information except utilized by this sample application is being used from global variables

   Parameters: empty string to be filled.

*/

function getRequestInputs(parametersString)

{

     for (var i   in operation.getInputParts () ) {

          // Just an illustration how to differentiate document style and RPC style calls

          if (!operation.getInputParts ()[i].isDocumentStyle())

                parametersString += getHtmlInput(

                                                      operation.getInputParts ()[i].getName(),

                                                      operation.getInputParts ()[i].getName());

          else {

                var documentStyleElement = operation.getInputParts ()[i].getDocumentStyleElement ();

                documentStyleElement.parseElement ();

                 var children = documentStyleElement.getChildren ();

                 for (var child in children) {

                       parametersString += getInputs(children[child], child);

                 }

          }

     }

     return parametersString;

}

/**

 Method for filling all subelements as inputs

 It works recursive for all sub-types so you don't need to call it for custom types in document style calls

 Parameters: element name or XSD element

                    Type name of that element

   

 */

function getInputs(element, name)

{

     var parametersString = "";

     // If sub-type defined we need to parse it and surround to separate div layer

     if (!wsdlInfo.getSchemaElements ()[element['type']])

          parametersString += getHtmlInput(name, name);

      else {

          var innerElements = wsdlInfo.getSchemaElements ()[element['type']].getXmlSimpleElements();

          parametersString += '<div align="right" id = "' + name + '">';

          for (var i in innerElements) {

                parametersString += getInputs(innerElements[i], i)

          }

           parametersString += '</div>';

      }

       return parametersString;

}

/**

 Get html button: supplementary simple method

  In case you don't need dynamic HTML controls you can use static button name instead with

      <input type=button value="." class="buttonType" onClick="invoke()">

  Parameters: exact name of button to be shown.

 */

function getHtmlButton(value)

{

     var button = '';

     button += " <br><br>";

     button += "<input type=\"button\" value=\"" + value + "\" onclick=\"invoke()\"";

     button += " class=\"buttonType\"/>";

     button += getSpace(4) + "<br><br>";

     return button;

}

/**

 Get space: utility function that generates "&nbsp;" symbols as it needs by first parameter

 */

function getSpace(count)

{

     var string = '';

     for (var i = 0; i < count; ++i)

          string += '&nbsp;';

     return string;

}

/**

 Get html input element for dynamic inputs creation

 This is utility function that creates label : input field fior every call.

 It might be replaced to use pool of statically defined elements like

  <br>. : <input type="text" id="." value="" class="inputType"/>

  .

 Parameters: Label to be shown

                    Id to be bounded to text element

 */

function getHtmlInput(name, id)

{

     var input = '';

     input += '<br><strong><label>' + name + ' : </label></strong>';

     input += "<input type=\"text\" id=\'" + id + "\' value=\"\"";

     input += " class=\"inputType\" />";

     input += getSpace(4);

     return input;

}   

As result you'll see behavior like follows:

Step 4: Invoke  and parse response

There is pretty simple: by pressing button at the bottom on screenshot web service will be called. But we need to collect information from controls we created earlier, and pass it to web service:

/**

 Create request parameters from HTML elements, based upon WSDL information

 Here we need to separate RPC and document-style calls because document-style calls may use

 Separate namespaces for every subtype definition.

 

 Parameters: XSD element or element name

                    Name to be used in request

 */

function getRequestParametersAsArray(element, name)

{

     var params = new Array();

     if (!element['isArray'])

           // If sub-type defined we need to discover values recursively

           if ( !wsdlInfo.getSchemaElements ()[element['type']] ){

                var value = document.getElementById(name).value;

                params[name] = value;

          }

          else {

                var innerElements = wsdlInfo.getSchemaElements ()[element['type']].getXmlSimpleElements();

                var innerParams = new Array();

                for (var i in innerElements) {

                     innerParams[i] = getRequestParametersAsArray(innerElements[i], i);

                }

                params[name + ' xmlns="' + element['namespace'] + '"'] = innerParams;

          }

    }

    return params;

}

/**

 Invoke  current method and fill  response elements

 Parameters: none

 Globals: WSClient , operation

 */

function invoke()

{

     var parameters = new WSClientParameters ();

     var valid = true;

     if ( operation.getInputParts () ) {

       /** Fill request parameters dynamicaly*/

       if (document.getElementById("selectType").value == "false")

       {

          for (var i  in operation.getInputParts ()) {

               if ( !operation.getInputParts ()[i].isDocumentStyle()) {

                     var value = document.getElementById( operation.getInputParts () [i].getName () ).value;

                     parameters.add(operation.getInputParts () [i].getName () , value);

              }

              else {

                   var documentStyleElement = operation.getInputParts () [i]

                                                               .getDocumentStyleElement ();

                   documentStyleElement.parseElement ();

                   var children = documentStyleElement.getChildren ();

                   for (var j in children) {

                         parameters.add(j, getRequestParametersAsArray(children[j], j));

                   }

               }

          }

        }

        /**creating input parameters by hand*/

        else

        {

            if (operation.getName() != "GetGeoIPContext")

            {

                var ip = new Array();

                ip["IPAddress"] = document.getElementById("IPAddress").value;

                parameters.add("GetGeoIP", ip);

             }

        }

        if (valid) {

              var result = operation.invoke(parameters, false, null);

              var out_parts = operation.getOutPutParts ();

              var resultString = '';

              for (var i  in out_parts) {

                    if (!out_parts[i].isDocumentStyle()) {

                           resultString += getHtmlOutput(

                                                          out_parts[i].getName (),

                                                          out_parts[i].getName (),

                                                          result[out_parts[i].getName ()]);

                     }

                     else {

                           resultString += parseResponse(result);

                     }

              }

              document.getElementById('response').innerHTML = resultString;

              document.getElementById('response').style.display = "";

        }

    }

}

Now we have last task: parse response and display it on html page. We'll do it like input parameters:

/**

 Create response HTML elements

 Parses result array. This function determines complex and simple types and

 handles it differntly, so there is good point to understand how it collects in response

 Parameters: response from invoke() call

                    Name to be handled

 */

function parseResponse(result, name)

{

     var html = "";

     for (var p in result) {

         //  if element is complex type

         if (typeof(result[p]) == "object") {

              if (result[p]) {

                   if (typeof(result[p][0]) == "undefined")

                        html += parseResponse(result[p])

                   else

                        html += parseResponse(result[p], p);

              }

        }

       // element is a simple type

       else if (typeof(result[p]) != "function")

             if (name)

                   html += getHtmlOutput(name, name, result[p]);

             else

                   html += getHtmlOutput(p, p, result[p]);

       }

       return html;

}

/**

 Create HML outbox: simple utility function

 Parameters: Label

                    ID to be surrounded to response values

                    Value

 */

function getHtmlOutput(name, id, value)

{

    var input = '';

    input += '<br><strong><label>' + name + ' : </label></strong>';

    input += "<input type=\"text\" id=\'" + id + "\' readonly value=\"" + value + "\"";

    input += " class=\"resultType\" />";

    input += getSpace(4);

    return input;

}

/**

 Clear all inputs: simple function that hides input and response layers

 */

function clearAll()

{

    document.getElementById('staticInput').style.display = "none";

    document.getElementById('response').style.display = "none";

}

Now if you invoke method you'll see invocation result:

 

Of course with your IP you'll get other response but there is good illustration.

Recognizing complex types and arrays by hands

As we know all input/output parameters for "GeoServiceIp" operations, we can use this knowledge for creating input parameters by hand:

/**

 Invoke  current method

 */

function invoke()

{

     var parameters = new WSClientParameters ();

     var valid = true;

     if ( operation.getInputParts () ) {

       /** Fill request parameters dynamicaly*/

       if (document.getElementById("selectType").value == "false")

       {

          for (var i  in operation.getInputParts ()) {

               if ( !operation.getInputParts ()[i].isDocumentStyle() ) {

                     var value = document.getElementById( operation.getInputParts class=SourcesimportantChar> () [i].getName () ).value;

                     parameters.add(operation.getInputParts () [i].getName () , value);

              }

              else {

                   var documentStyleElement = operation.getInputParts () [i]

                                                               .getDocumentStyleElement ();

                   documentStyleElement.parseElement ();

                   var children = documentStyleElement.getChildren ();

                   for (var j in children) {

                         parameters.add(j, getRequestParametersAsArray(children[j], j));

                   }

               }

          }

        }

        /**creating input parameters by hand*/

        else

        {

            if (operation.getName() != "GetGeoIPContext")

            {

                var ip = new Array();

                ip["IPAddress"] = document.getElementById("IPAddress").value;

                parameters.add("GetGeoIP", ip);

             }

        }

        if (valid) {

              var result = operation.invoke(parameters, false, null);

              var out_parts = operation.getOutPutParts ();

              var resultString = '';

              for (var i  in out_parts) {

                    if (!out_parts[i].isDocumentStyle()) {

                           resultString += getHtmlOutput(

                                                          out_parts[i].getName (),

                                                          out_parts[i].getName (),

                                                          result[out_parts[i].getName ()]);

                     }

                     else {

                           resultString += parseResponse(result);

                     }

              }

              document.getElementById('response').innerHTML = resultString;

              document.getElementById('response').style.display = "";

        }

    }

}

In contrast to simple examples, this way describes how to handle complex types, auto-generated HTML controls, and more, but with full knowledge how it works and how it handles complex types, arrays and more.

Please note this code is an "improvement" to advanced example and it based upon functions described above.

WSDL and JavaScript mapping

Let's look closely for this part of JavaScript code and WSDL part:

if (operation.getName () != "GetGeoIPContext")

 {

        var ip = new Array();

        ip["IPAddress"] = document.getElementById("IPAddress").value;

        parameters.add("GetGeoIP", ip);

 }

So there is easy to use either WSDL or our WebService  Explorer tool to find proper names.



AJAX WebService Component: Overview Download License Architecture Tutorial API Support
WebService Explorer Overview Download License Guide Support
    Copyright © SCAND LLC, 2007. All Rights Reserved.