Call external web service using new CU 1290

With Nav 2015 there came some new objects. One of them is CU 1290 “Web Service Request Mgt.”.

Here is a short sample, how to use it:

the variables:
url : Text
reqText : Text
webServReqMgt : Codeunit : Web Service Request Mgt.
reqBodyOutStream : OutStream
reqBodyInStream : InStream
username : Text
password : Text
respBodyInStream : InStream
responseXmlDoc : DotNet : System.Xml.XmlDocument.’System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′
tempBlob : Record : TempBlob
action : Text

the code:
url := ´http://www.dneonline.com/calculator.asmx´;
//set body content of soap envelope
reqText := ´<add><inta>1</inta><intb>2</intb></add>´;
action := ´http://tempuri.org/Add´;

// save request text in instream
tempBlob.”Primary Key” := 1;
tempBlob.Blob.CREATEOUTSTREAM(reqBodyOutStream);
reqBodyOutStream.WRITE(reqText);
tempBlob.Blob.CREATEINSTREAM(reqBodyInStream);

// run the WebServReqMgt functions to send the request
webServReqMgt.SetGlobals(reqBodyInStream,url,username,password);
webServReqMgt.SetCustomGlobals(TRUE,action,FALSE,”,”);
webServReqMgt.DisableHttpsCheck;
webServReqMgt.SetTraceMode(TRUE); //to check the xml messages
webServReqMgt.SendRequestToWebService;

// get the response
webServReqMgt.GetResponseContent(respBodyInStream);
responseXmlDoc := responseXmlDoc.XmlDocument;
responseXmlDoc.Load(respBodyInStream);
MESSAGE(responseXmlDoc.InnerXml);

As you can see Username and Password are empty. That’s ok, if you run the call within the same AD or like in most cases, the target web service needs no authentication.

Changes in CU 1290
Using Credentials
for the case, you want to use credentials, do the following:
add local variable
NetCredential : DotNet : System.Net.NetworkCredential.’System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′

fct. BuildWebRequest:
replace
HttpWebRequest.UseDefaultCredentials := TRUE;
by
IF (GlobalUsername ”) AND (GlobalPassword ”) THEN BEGIN
  NetCredential := NetCredential.NetworkCredential(GlobalUsername,GlobalPassword);
  HttpWebRequest.Credentials := NetCredential;
END ELSE
  HttpWebRequest.UseDefaultCredentials := TRUE;

replace
HttpWebRequest.ContentType := ContentTypeTxt;
by
HttpWebRequest.ContentType := ‘text/xml;charset=utf-8’;

ContentTypeTxt has value “multipart/form-data; charset=utf-8”.
the web service call won’t work with that content type.

add these lines:
IF SoapAction <> ” THEN
  HttpWebRequest.Headers.Add(‘SOAPAction’, SoapAction);

new fct. SetCustomGlobals(useXmlMsgTypePar: Boolean;soapActionPar : Text;skipNsPar : Boolean;nsPrefixPar : Text;nsTxtPar : Text)
  UseXmlMsgType := useXmlMsgTypePar;
  SoapAction := soapActionPar;
  SkipDefaultNamespaces := skipNsPar;
  CustomNamespacePrefix := nsPrefixPar;
  CustomNamespaceTxt := nsTxtPar;

cheers

31 thoughts on “Call external web service using new CU 1290

  1. Nab says:

    Hello,

    Thank you for the post. Can you please give us a hint on how to build the “reqText” automatically (C/AL code or .net) ? Maybe how we can do that using the WSDL ?

    Best regards

    Like

  2. Nab says:

    Hi Jonathan,

    Thank you for taking time to answer me. The idea to use CU 6224 is the way to go for me (for the tests I’m doing at least). The problem is that I do not know how to build the ReqText as you did.

    Here is the scenario I’m testing ; I created a CU with the following function:

    DoUppercase(InputText : Text) : Text
    EXIT(UPPERCASE(InputText));

    I published the CU as a WS. Then I used the code you provide, I changed the URL and the ReqText as below:

    URL := ‘http://localhost:7047/Cronus906W1/WS/CRONUS%20International%20Ltd.%202/Codeunit/mywebservice’;
    ReqText := ”+’uppercase this for me’+”;

    When I run the CU to consume the ‘mywebservice’, I get this error “The expected data was not received from the web service” (no matter the credentials I use -Default or User/Password-).

    Can you please help me with that? –> I’m using NAV 2016 W1 CU6 by the way.

    P.S: your example works fine with URL = ‘http://www.w3schools.com/xml/tempconvert.asmx’. I believe w3schools updated the link since you wrote this article 🙂

    Like

  3. Nab says:

    In fact, I changed this also (The CU 1290 structure has changed):

    //SOAPWebServiceRequestMgt.RUN;
    SOAPWebServiceRequestMgt.SendRequestToWebService;

    The error I get is related to the function “ExtractContentFromResponse” (in CU 1290). This function fails because I get the WSDL structure as a response from “mywebservice”. Now, I’m trying to understand why I get the WSDL for response…

    Like

  4. i developed a simple web service in c#.

     namespace WebServiceNS  
     {  
       [WebService(Namespace = "http://tempuri.org/")]  
       [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]  
       [System.ComponentModel.ToolboxItem(false)]  
       public class WebService1 : System.Web.Services.WebService  
       {  
         [WebMethod]  
         public string GetUpperCase(string lowerCaseText)  
         {  
           if (!string.IsNullOrEmpty(lowerCaseText))  
             return lowerCaseText.ToUpper();  
           return string.Empty;  
         }  
       }  
     }  
    

    then i ran the new webservice with http://localhost:63427/WebService1.asmx?op=GetUpperCase
    in the browser window you can then see the wsdl code:

    POST /WebService1.asmx HTTP/1.1
    Host: localhost
    Content-Type: text/xml; charset=utf-8
    Content-Length: length
    SOAPAction: “http://tempuri.org/GetUpperCase”

     <?xml version="1.0" encoding="utf-8"?>  
     <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">  
      <soap:Body>  
       <GetUpperCase xmlns="http://tempuri.org/">  
        <lowerCaseText>string</lowerCaseText>  
       </GetUpperCase>  
      </soap:Body>  
     </soap:Envelope>  
    

    to call the web service with c/al and set the correct value for reqText, simply copy the lines between the soap:Body tag.
    so the value for reqText in that case is:

     reqText := '<GetUpperCase xmlns="http://tempuri.org/"><lowerCaseText>hello</lowerCaseText></GetUpperCase>';  
    

    GetUpperCase is the webmethod name , tag property xmlns is set with the namespace defined as attribute in the c# webmethod. lowercasetext is the name of the parameter. so it’s quite simple to use.

    the result, when calling that web service:

     <GetUpperCaseResponse xmlns="http://tempuri.org/"><GetUpperCaseResult>HELLO</GetUpperCaseResult></GetUpperCaseResponse>  
    

    you can see: hello is converted to HELLO.. 😉

    cheers

    Like

  5. Hi Jonathan, I am getting a fallowing error when i run same code . If possible please let me know how to resolve this error.

    Microsoft Dynamics NAV
    —————————

    A call to System.Xml.XmlDocument.Load failed with this message: Root element is missing.
    —————————
    OK
    —————————

    Like

  6. HI Moxie, I got another response after few changes to service

    Microsoft Dynamics NAV
    —————————

    A call to System.Net.HttpWebRequest.GetResponse failed with this message: The remote server returned an error: (500) Internal Server Error.
    —————————
    OK
    —————————

    Like

    • eka says:

      Hi Jonathan,
      Thanks for your fast response. But i still get the same error. Note : i’m using NAV 2016 CU 12. Thanks

      Url := ‘http://www.w3schools.com/xml/tempconvert.asmx’;

      reqText := ” +
      ‘string’ +
      ”;

      // save request text in instream
      TempBlob.”Primary Key” := 1;
      TempBlob.Blob.CREATEOUTSTREAM(ReqBodyOutStream);
      ReqBodyOutStream.WRITE(reqText);
      TempBlob.Blob.CREATEINSTREAM(ReqBodyInStream);

      // run the WebServReqMgt functions to send the request
      WebServReqMgt.SetGlobals(ReqBodyInStream,Url,Username,Password);
      WebServReqMgt.DisableHttpsCheck;
      WebServReqMgt.RUN;

      // get the response
      WebServReqMgt.GetResponseContent(RespBodyInStream);
      ResponseXmlDoc := ResponseXmlDoc.XmlDocument;
      ResponseXmlDoc.Load(RespBodyInStream);
      MESSAGE(ResponseXmlDoc.InnerXml);

      Like

  7. AmarR says:

    Hi jonathan,
    Thank you for such a wonderful post. 🙂

    I am trying to integrate NAV 2016 with Salesforce and I am using the CU 1290, I tried with your above code to send the authentication request but I am getting an error: A call to System.Xml.XmlDocument.Load failed with this message: Root element is missing.

    I saw your ‘call-external-web-service-using-cu-1290-part-2’ page as well but didn’t find any parameters in soap:Body tag in my case (WSDL file). I don’t know what value “reqText” must have in my case. I can only find


    defined numerous times throughout the wsdl file.

    Kindly help me, I am stuck here.

    Like

  8. JJ says:

    Hi Jonathan
    I was trying to consume a NAV webservice in NAV using CU 1290.
    I came across this very useful post of yours and incorporate it into the codes.
    After solving the credential and content type issues, i ran into this error:
    “The expected data was not received from the web service”.

    I had turned on the tracelog, and was able to see the FullRequest.XML file in the temp folder, and this is my FullRequest.
    (I put the whole script into SOAPUI and it works without error )



    WebServCust

    So i have already read somewhere that CU 1290 is not built to handle NAV webservice, is it the case?

    (The reason why i am doing this is, i have a client that has 60 companies in the system and they requested some functionalities to be done across all other companies from one single page without having to open up each company. Normally, using NAV codes, we would use CHANGECOMPANY method to handle this, however, lot of validation triggers will have to be replicated. To avoid this, i read that i can use Webservice to handle this since i can pass the company name in the URL and all the validation triggers will work as usual.)

    Since this post is rather old, i hope you still monitor the post for new comments. Thank you in advance for your time.

    JJ

    Like

  9. Tsveta says:

    Hi,
    I’m trying to call external web service from NAV 2018. I use codeunit 1290 and WebServReqMgt.DisableHttpsCheck is not a option for me. I could use https and certificate and I could not understand is it possible to call external web service with certificate. Where I could said, which certificate I want to use.
    When I test access to this web service the error is
    A call to System.Net.HttpWebRequest.GetResponse failed with this message: The request was aborted: Could not create SSL/TLS secure channel.

    So do you know is this possible or not.
    Best Regards,

    Like

Leave a comment