Monday, August 8, 2022

How to consume web service on Navision 5.0

 Based on walkthrough from Microsoft (https://docs.microsoft.com/en-us/dynamics-nav/walkthrough--creating-and-using-a-codeunit-web-service--soap-), it will consume the web service by creating .NET application. I would like to consume it from Navision 5.0 and the pseudocode as follows:

WinHttp

DataType = Automation

Subtype = 'Microsoft WinHTTP Services, version 5.1'.WinHttpRequest


IF ISCLEAR(WinHttp) THEN

   CREATE(WinHttp);

XMLHttp.open('POST','http://<localhostname>/DynamicsNAV110/WS/CRONUS%20International%20Ltd./Codeunit/Letters');

XMLHttp.setRequestHeader('Content-Type', 'text/xml; charset=utf-8');

XMLHttp.setRequestHeader('SOAPAction','Capitalize');


XMLHttp.send(

  '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' +

  '<soap:Body><' + 'Capitalize' + ' xmlns="urn:microsoft-dynamics-schemas' + '/codeunit/Letters' + '">' +

  '<inputstring>'+'testmessage'+'</inputstring>' +  // Parameter 1

  '</' + 'Capitalize' + '></soap:Body></soap:Envelope>');


// If status is OK - Get Result XML

IF XMLHttp.status=200 THEN

BEGIN

XMLDoc.load(XMLHttp.responseXML);

XMLDoc.save('D:\XMLResponse1.xml');

END;

CLEAR(XMLHttp);


Note. Dynamic way to construct XML request message is using the following method (https://freddysblog.com/2010/01/21/connecting-to-nav-web-services-from-microsoft-dynamics-nav-2009-sp1/)


Important!!!

'Microsoft XML, v6.0'.DOMDocument60 >> issue on blank "xmlns" so that need to use 'Microsoft XML, v3.0'.DOMDocument30 instead. 

<Soap:Envelope xmlns:Soap="http://schemas.xmlsoap.org/soap/envelope/">

<Soap:Body>

<Capitalize xmlns="urn:microsoft-dynamics-schemas/codeunit/Letters">

<inputstring xmlns="">Hello test capital</inputstring>

</Capitalize>

</Soap:Body>

</Soap:Envelope>


Sample codes for dynamic way:

Var Name                     DataType Subtype Length

No URL                     Text                 250

No method                     Text                 20

No nameSpace             Text                 80

No returnTag                     Text                 20

No parameters             Text                 1024

No nodeList                     Automation 'Microsoft XML, v3.0'.IXMLDOMNodeList


Return Value

Name = result

Return Type = Boolean


 Name                           DataType    Subtype 

 xmlhttp                        Automation 'Microsoft XML, v6.0'.XMLHTTP60

 xmldoc                        Automation 'Microsoft XML, v3.0'.DOMDocument30

 soapEnvelope             Automation 'Microsoft XML, v3.0'.IXMLDOMElement

 soapBody                    Automation 'Microsoft XML, v3.0'.IXMLDOMElement

 soapMethod                Automation 'Microsoft XML, v3.0'.IXMLDOMElement

 node                            Automation 'Microsoft XML, v3.0'.IXMLDOMNode

 parametersXmlDoc    Automation 'Microsoft XML, v3.0'.DOMDocument30


Res    := InvokeNavWS(

          'http://<localhostname>/DynamicsNAV110/WS/CRONUS%20International%20Ltd./Codeunit/Letters',

          'Capitalize', 

          'urn:microsoft-dynamics-schemas/codeunit/Letters',

           'return_value',

           '<inputstring>Hello test capital</inputstring>', nodeList);

           //'', nodeList);


InvokeNavWS Function:


result := FALSE;


// Create XML Document

CREATE(xmldoc,TRUE);


// Create SOAP Envelope

soapEnvelope := xmldoc.createElement('Soap:Envelope');

soapEnvelope.setAttribute('xmlns:Soap', 'http://schemas.xmlsoap.org/soap/envelope/');

xmldoc.appendChild(soapEnvelope);


// Create SOAP Body

soapBody := xmldoc.createElement('Soap:Body');

soapEnvelope.appendChild(soapBody);


// Create Method Element

soapMethod := xmldoc.createElement(method);

soapMethod.setAttribute('xmlns', nameSpace);

soapBody.appendChild(soapMethod);


// Transfer parameters by loading them into a XML Document and move them

CREATE(parametersXmlDoc,TRUE);

parametersXmlDoc.loadXML('<parameters>'+parameters+'</parameters>');

IF parametersXmlDoc.firstChild.hasChildNodes THEN

BEGIN

  WHILE parametersXmlDoc.firstChild.childNodes.length>0 DO

  BEGIN

    node := parametersXmlDoc.firstChild.firstChild;

    node := parametersXmlDoc.firstChild.removeChild(node);

    soapMethod.appendChild(node);

  END;

END;


xmldoc.save('D:\XMLRequest.txt');


// Create XMLHTTP and SEND

CREATE(xmlhttp, TRUE);

xmlhttp.open('POST',URL,FALSE);

xmlhttp.setRequestHeader('Content-type', 'text/xml; charset=utf-8');

xmlhttp.setRequestHeader('SOAPAction',method);


xmlhttp.send(xmldoc);


MESSAGE(FORMAT(xmlhttp.status) + ' ' + xmlhttp.statusText);


// If status is OK - Get Result XML

IF xmlhttp.status=200 THEN

BEGIN

  //xmldoc := xmlhttp.responseXML;


  //get the response

  xmldoc.load(xmlhttp.responseXML);

  xmldoc.setProperty('SelectionLanguage','XPath');

  xmldoc.setProperty('SelectionNamespaces','xmlns:tns="'+nameSpace+'"');

  nodeList := xmldoc.selectNodes('//tns:'+returnTag);


  nodeList := xmldoc.getElementsByTagName('return_value');

  FOR i:=0 TO nodeList.length()-1 DO BEGIN

    MESSAGE(nodeList.item(i).text);

  END;


  //this is for diagnostics only, so you can see what you got back

  xmldoc.save('D:\XMLResponse1.xml');


  result := TRUE;

END;