1

I want to consume the WebService from Microsoft Dynamics NAV 2009 with a small node.js application. The Service itself works fine, I am using it with a c# application, now I want to get data into my nodejs/expressjs application but, I always get Invalid WSDL URL as an error message.

Here is the WSDL as my Browser sees it.

enter image description here

Now I tried to connect with node-soap, following the documentation, by normal and by basic auth, but everytime I get an Invalid WSDL URL error.

Here are the methods I tried for a test connection:

    var url = "http://navsrv:7047/DynamicsNAV2/WS/Produktiv/Page/WDCETA";
    var auth = "Basic " + new Buffer("*********" + ":" + ****************").toString("base64");

    soap.createClient(url, function(err, client) {
      console.log('Without basic out:');

      if (err)
      {
        console.log('[ERROR] -> ');
        console.log(err);
      }

      console.log(client);
    });


    soap.createClient(url, {wsdl_headers: {Authorization: auth} }, function(err, client) {
      console.log('With basic out:');
      if (err)
      {
        console.log('[ERROR] -> ');
        console.log(err);
      }
      console.log(client);
    });

And this is the response I get:

Without basic out:
[ERROR] ->
[Error: Invalid WSDL URL: http://navsrv:7047/DynamicsNAV2/WS/Produktiv/Page/WDDCETA

 Code: 401

 Response Body: ]
undefined

With basic out:
[ERROR] ->
[Error: Invalid WSDL URL: http://navsrv:7047/DynamicsNAV2/WS/Produktiv/Page/WDDCETA

 Code: 401

 Response Body: ]
undefined
Ello
  • 907
  • 1
  • 15
  • 33
  • 1
    After a little debugging I found out that I have to send a ntml/negotiate header not a basic auth header. I will try to accomplish it with node-soap to send a negotiate header then edit/answer this question accordingly – Ello Aug 14 '15 at 12:07
  • You can use httpntlm client, here is a complete example: https://stackoverflow.com/a/68823338/10030693 – Gilbert Aug 17 '21 at 20:02

1 Answers1

1

As it turned out, the build in HTTP-Server from DyanmicsNAV requires SPNEGO or NTLM as authentication. After some tries creating a proper SPNEGO request with nodejs/node-soap I turned off SPNEGO and enabled NTLM.

With the help of soap-ntlm and httpntlm I could retrieve the wsdl.

This is some testing code how I could manage to retrieve the WSDL file. For now I am happy, but I guess when it comes to invoke function there will be some other issues :)

var soap = require('soap-ntlm');
var fs = require('fs');
var httpntlm = require('httpntlm');

var url = 'http://navsrv:7047/DynamicsNAV2/WS/Produktiv/Page/WDCETA';
var username = '*******';
var password = '***********';



httpntlm.get({
  url: url,
  password: password,
  username: username
}, function(err, wsdl) {
  if (err)
  {
      console.log('ERR: -> ');
      console.log(err);
      return;
  }
  fs.writeFile('wsdl_cache/WDCETA.wsdl', wsdl.body, function() {

    soap.createClient(__dirname + '/wsdl_cache/WDCETA.wsdl', function(err, client) {
      if (err) {
        console.log('SOAP ERR: ->');
        console.log(err);
        return;
      }

      client.setSecurity(new soap.NtlmSecurity(username, password));

      console.log(client);
    });

  })

});
Ello
  • 907
  • 1
  • 15
  • 33
  • SPNEGO with node is possible using kerberos module. See this Gist: https://gist.github.com/dmansfield/c75817dcacc2393da0a7 – dmansfield Aug 31 '15 at 20:36
  • yes thank you. I did know that SPNEGO is possible, but I did not get it to work properly, so i used NTLM instead to get at least any progress for now. The connection works fine with NTLM by now and, because DynamicsNAV is some kind of picky when it comes to standars, i was happy that it worked. But I will give SPNEGO another try in a couple of days. Thank you for your respond. – Ello Aug 31 '15 at 20:46
  • @Ello: Does your given example work for you? Because When i am trying with this code, it is giving me some error on nodeJS like, Provided call is not a callback from httpntlm library. – Pritam Jun 27 '16 at 04:49
  • @Ello: Further more, Can you please tell me, what kind of Authentication type have you set for Dynamics login? Windows or UserName or NavUserPassword or AccessControlService? – Pritam Jun 27 '16 at 04:55
  • I use corresponding username/password credentials as assigned by nav/mssql server. Never tried Windows Auth tho. I double checked and yes, basicly this is the code i am running besides the console.log is replaced with client.ReadMultiple (or what method you want invoke) – Ello Jun 27 '16 at 11:22
  • @Pritam well I just saw i am using soap-ntlm, maybe this is the issue? so `var soap = require('soap-ntlm')` maybe you are using the wrong package? – Ello Jun 27 '16 at 11:24
  • @Ello: Thanks for your response. and yes, I am doing the same code as you mentioned in this example. Also, i have got installed package the same. Don't know what can be the issue now. – Pritam Jun 27 '16 at 11:49
  • @Ello: By this way, I was able to connect to NAV, but now the problem is that, I am not able to use any of Clients functions. e,g client.Read(No,callback{}); It gives me error of ``401`` – Pritam Dec 10 '16 at 04:41
  • client.Read:: {"response":{"statusCode":401,"body":"","headers":{"content-length":"0","server":"Microsoft-HTTPAPI/2.0","www-authenticate":"NTLM","date":"Tue, 06 Dec 2016 19:28:57 GMT","connection":"close"},"request":{"uri":{"protocol":"http:","slashes":true,"auth":null,"host":"localhost:7047","port":"7047","hostname":"localhost","hash":null,"search":null,"query":null,"pathname":"/DynamicsNAV/WS/CRONUS/Page/Customer_Card","path":"/DynamicsNAV/WS/CRONUS/Page/Customer_Card","href":"http://localhost:7047/DynamicsNAV/WS/CRONUS/Page/Customer_Card"},"method":"POST", – Pritam Dec 10 '16 at 04:43
  • "headers":{"User-Agent":"node-soap/0.18.0","Accept":"text/html,application/xhtml+xml,application/xml,text/xml;q=0.9,*/*;q=0.8","Accept-Encoding":"none","Accept-Charset":"utf-8","Connection":"close","Host":"localhost:7047","Content-Length":349,"Content-Type":"text/xml; charset=utf-8","SOAPAction":"\"urn:microsoft-dynamics-schemas/page/customer_card:Read\""}}},"body":""} – Pritam Dec 10 '16 at 04:43
  • Does your NAV webservice work in general? Can you connect with the nav webclient? How about the user credentials, does the user you are trying to connect with has access rights and is setup as MSSQL user as well ? Is the CustomerCard setup properly in table `Web Service` and is the page published? – Ello Dec 12 '16 at 08:33
  • @Pritam Did you turn off SPENGO and turn on NTML in the service config ? – Ello Dec 12 '16 at 08:40
  • @Ello. Yes. Only After Checking the option of NTML, NAV allowed the connection. – Pritam Dec 12 '16 at 09:15
  • @Ello Did you every get this working with nodejs to pull data from codeunits? – Adam91Holt Mar 21 '17 at 09:27
  • @Adam91Holt I did not try that directly, but what I did is that i created a field on the page that gets populated by the service and fill the field at the OnAfterGetRecord trigger by a value from a Codeunit, for the consuming end the "on the fly field" looks like a normal field. However this works only for the Read and ReadMultiple functions, I don't know if you could get this work for Write aswell, maybe if you add actions to the OnModify of the page – Ello Mar 21 '17 at 12:30
  • @Ello - Awesome, I don't suppose you could upload some of the code to github for me to take a look do you? My work integrates with Nav via vb.net but I hate it and I love NodeJs. If thats ok my github username is the same as here, if not no worries at all :) Cheers – Adam91Holt Mar 23 '17 at 22:15
  • @Adam91Holt There is nothing really interesing at C/AL side. You go to the page you are publishing by the service, create a new Field, create a global variable, bind the variable to the source expression of the field and fill your variable in the OnAfterGetRecord Trigger. How you fill the variable (directly, by Codeunit) is up to you. When you consume your page by WebService you now have a new field/column with data in it. So on the consuming side of view (e.g. nodejs) you just have a new field. The downside, you can use this method for the Read and ReadMultiple functions. Update gets tricky – Ello Mar 24 '17 at 08:24
  • @Adam91Holt Hi, I'm in a similar situation, and I'm getting the following error: "Error: Couldn't find NTLM in the message type2 comming from the server" Any Ideas on that to do now, thanks. Is it because I need to add to the webservice? – Niels Robin Aagaard May 24 '19 at 12:39
  • Here is a full example: https://stackoverflow.com/a/68823338/10030693 – Gilbert Aug 17 '21 at 20:02