Connecting to NAV Web Services from PHP


Prerequisites

Please read this post to get an explanation on how to modify the service tier to use NTLM authentication and for a brief explanation of the scenario I will implement in PHP.

BTW. Basic knowledge about PHP is required to understand the following post:-)

Version and download

In my sample I am using PHP version 5.2.11, which I downloaded from http://www.php.net, but it should work with any version after that.

In order to make this work you need to make sure that SOAP and CURL extensions are installed and enabled in php.ini.

PHP does not natively have support for NTLM nor SPNEGO authentication protocols, so we need to implement that manually. Now that sounds like something, which isn’t straightforward and something that takes an expert.   Fortunately there are a lot of these experts on the internet and I found this post (written by Thomas Rabaix), which explains about how what’s going on, how and why. Note that this implements NTLM authentication and you will have to change the Web Services listener to use that.

License of the code

The code can be used freely as long as you include Thomas’ copyright notice in the code.

/*
* Copyright (c) 2008 Invest-In-France Agency http://www.invest-in-france.org
*
* Author : Thomas Rabaix
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

“My” Version

I have modified Thomas’ version slightly (primarily removing debug echo’s etc.).

I have also changed the way the username and password is specified to be a script constant:

define(‘USERPWD’, ‘domain\user:password’);

The Stream wrapper now looks like:

class NTLMStream
{
    private $path;
    private $mode;
    private $options;
    private $opened_path;
    private $buffer;
    private $pos;
    /**
     * Open the stream
      *
     * @param unknown_type $path
     * @param unknown_type $mode
     * @param unknown_type $options
     * @param unknown_type $opened_path
     * @return unknown
     */
    public function stream_open($path, $mode, $options, $opened_path) {
        $this->path = $path;
        $this->mode = $mode;
        $this->options = $options;
        $this->opened_path = $opened_path;
        $this->createBuffer($path);
        return true;
    }
    /**
     * Close the stream
     *
     */
    public function stream_close() {
        curl_close($this->ch);
    }
    /**
     * Read the stream
     *
     * @param int $count number of bytes to read
     * @return content from pos to count
     */
    public function stream_read($count) {
        if(strlen($this->buffer) == 0) {
            return false;
        }
        $read = substr($this->buffer,$this->pos, $count);
        $this->pos += $count;
        return $read;
    }
    /**
     * write the stream
     *
     * @param int $count number of bytes to read
     * @return content from pos to count
     */
    public function stream_write($data) {
        if(strlen($this->buffer) == 0) {
            return false;
        }
        return true;
    }
    /**
     *
     * @return true if eof else false
     */
    public function stream_eof() {
        return ($this->pos > strlen($this->buffer));
    }
    /**
     * @return int the position of the current read pointer
     */
    public function stream_tell() {
        return $this->pos;
    }
    /**
     * Flush stream data
     */
    public function stream_flush() {
        $this->buffer = null;
        $this->pos = null;
    }
    /**
     * Stat the file, return only the size of the buffer
     *
     * @return array stat information
     */
    public function stream_stat() {
        $this->createBuffer($this->path);
        $stat = array(
            ‘size’ => strlen($this->buffer),
        );
        return $stat;
    }
    /**
     * Stat the url, return only the size of the buffer
     *
     * @return array stat information
     */
    public function url_stat($path, $flags) {
        $this->createBuffer($path);
        $stat = array(
            ‘size’ => strlen($this->buffer),
        );
        return $stat;
    }
    /**
     * Create the buffer by requesting the url through cURL
     *
     * @param unknown_type $path
     */
    private function createBuffer($path) {
        if($this->buffer) {
            return;
        }
        $this->ch = curl_init($path);
        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($this->ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($this->ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
        curl_setopt($this->ch, CURLOPT_USERPWD, USERPWD);
        $this->buffer = curl_exec($this->ch);
        $this->pos = 0;
    }
}

The NTLM SOAP Client also uses the USERPWD constant defined above and looks like:

class NTLMSoapClient extends SoapClient {
    function __doRequest($request, $location, $action, $version) {
        $headers = array(
            ‘Method: POST’,
            ‘Connection: Keep-Alive’,
            ‘User-Agent: PHP-SOAP-CURL’,
            ‘Content-Type: text/xml; charset=utf-8’,
            ‘SOAPAction: "’.$action.’"’,
        );
        $this->__last_request_headers = $headers;
        $ch = curl_init($location);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_POST, true );
        curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
        curl_setopt($ch, CURLOPT_USERPWD, USERPWD);
        $response = curl_exec($ch);
        return $response;
    }

    function __getLastRequestHeaders() {
        return implode("\n", $this->__last_request_headers)."\n";
    }
}

Putting this into the PHP script now allows you to connect to NAV Web Services system service in PHP and output the companies available on the service tier:

// we unregister the current HTTP wrapper
stream_wrapper_unregister(‘http’);
// we register the new HTTP wrapper
stream_wrapper_register(‘http’, ‘NTLMStream’) or die("Failed to register protocol");

// Initialize Soap Client
$baseURL = ‘
http://localhost:7047/DynamicsNAV/WS/’;
$client = new NTLMSoapClient($baseURL.’SystemService’);

// Find the first Company in the Companies
$result = $client->Companies();
$companies = $result->return_value;
echo "Companies:<br>";
if (is_array($companies)) {
  foreach($companies as $company) {
    echo "$company<br>";
  }
  $cur = $companies[0];
}
else {
  echo "$companies<br>";
  $cur = $companies;
}

Note that is return value is an array if there are multiple companies, but a company name if there is only one. I have NO idea why this is or whether I can write the code differently to avoid this.

Now I have the company I want to use in $cur and the way I create a URL to the Customer page is by doing:

$pageURL = $baseURL.rawurlencode($cur).’/Page/Customer’;
echo "<br>URL of Customer page: $pageURL<br><br>";

and then I can create a Soap Client to the Customer Page:

// Initialize Page Soap Client
$page = new NTLMSoapClient($pageURL);

and using this, I read customer 10000 and output the name:

$params = array(‘No’ => ‘10000’);
$result = $page->Read($params);
$customer = $result->Customer;
echo "Name of Customer 10000:".$customer->Name."<br><br>";

Last, but not least – lets create a filter and read all customers in GB that has Location Code set to RED or BLUE:

$params = array(‘filter’ => array(
                                    array(‘Field’ => ‘Location_Code’,
                                          ‘Criteria’ => ‘RED|BLUE’),
                                    array(‘Field’ => ‘Country_Region_Code’,
                                          ‘Criteria’ => ‘GB’)
                                  ),
                ‘setSize’ => 0);
$result = $page->ReadMultiple($params);
$customers = $result->ReadMultiple_Result->Customer;

Note that Bookmark is an optional parameter and doesn’t need to be specified.

Now echo the customers and restore the http protocol – again, the return value might be an array and might not.

echo "Customers in GB served by RED or BLUE warehouse:<br>";

if (is_array($customers)) {
  foreach($customers as $cust) {
    echo $cust->Name."<br>";
  }
}
else {
  echo $customers->Name."<br>";
}

// restore the original http protocole
stream_wrapper_restore(‘http’);

All of the above will output this when the script is opened in a browser (on my machine running NAV 2009SP1 W1)

image_thumb[3]

I hope this is helpful.

Good luck

Freddy Kristiansen
PM Architect
Microsoft Dynamics NAV

Comments (63)

  1. gert789 says:

    Hey Freddy,

    I’m trying to use your php script to connect with my dynamics NAV web service but it fails to authenticate… I’ve tried to surf to the web services URL with internet explorer and that works  perfect…

    I’ve adjusted the config file…

    Is there something else I need to do?

    thanks!

    gert

  2. FreddyDK says:

    I know a number of people followed this example to successfully connect to NAV Web Services from PHP – so no.

    Setting WebServicesUseNTLMAuthentication to true in the CustomSettings.config is the only thing.

  3. gert789 says:

    Is it necessary to run NAV with a three tier server configuration?

    and which version of NAV did they use?

  4. FreddyDK says:

    3T or 2T – doesn’t matter, but it needs to be NAV 2009 SP1.

  5. gert789 says:

    and do I have to use some kind of proxy or delegations?

  6. FreddyDK says:

    Nothing special – everything you need is explained in this post and the first.

  7. TheSin says:

    Hey Freddie, thanks to your post I have most of my NAV 2009SP1 3 tier setup.  SPNs continue to give me grief and I’m assuming that in my NAV WS setup to use with php I’m running into that very issue.

    I’m running php5.2.12 on a none domain system running linux.  I’ve copied your code and even re added all the debug just to see what’s going on.  I can see and connect to the NAV Service tier on port 7047.  But it fails to pass on the credentials to the DB and I get the infamous ANONYMOUS login attempt in the SQL logs.

    My PHP is returning

    a:Microsoft.Dynamics.Nav.Types.NavDatabasePasswordExceptionThe login failed when connecting to SQL Server <SQL Server><SQL Instance>.The login failed when connecting to SQL Server <SQL Server><SQL Instance>.

    I have setup the http SPN records, and I’m using the service user/pass which I know are correct, if I do it with IE on the <Service Tier Server> it works perfect, so I know it’s SPN related and your example here doesn’t say anything about SPNs for the WS (http/<service tier>).

    Thanks for any help in this matter.

  8. larsl says:

    Hej Freddy,

    Jeg får en PHP fejl når jeg forsøger ovenstående eksempel:

    Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn’t load from ‘http://localhost:7047/DynamicsNAV/WS/SystemService”>http://localhost:7047/DynamicsNAV/WS/SystemService‘ : Start tag expected, ‘<‘ not found in D:wampwwwnavindex.php:10 Stack trace: #0 D:wampwwwnavindex.php(10): SoapClient->SoapClient(‘http://localhos…’) #1 {main} thrown in D:wampwwwnavindex.php on line 10

    Har du nogen idé til hvad problemet kan være? Jeg tror selv at det skyldes, at I mangler følgende i starten af den XML som sendes tilbage fra webservicen:

    <?xml version=’1.0′ encoding=’UTF-8′?>

    Hvis jeg gemmer XMLen som en fil og indsætter dette så går det meget bedre. Jeg undrer mig blot over at I ikke skulle være opmærksomme på dette hvis det er problemet?

    Jeg har oplevet det samme hvis jeg forsøge at bruge SOAPui til at explore NAV webservices. Dette program melder også fejl på samtlige XML filer fra NAV fordi denne tag mangler.

  9. FreddyDK says:

    It looks like you forgot to set the Service Tier to use NTLM authentication and restart both services (Web Service and Service tier)

  10. larsl says:

    Hi, Service Tier is set to use NTLM, so that is not the problem:

    <add key="WebServicesUseNTLMAuthentication" value="true"></add>

  11. TheSin says:

    I got mine running, for me it was the SPNs, took awhile to figure out, if you have all the proper SPNs on your domainuser running the services (if using a domain user) you have to select using any protocol, unlike the 3 tier setup that says to use kerb only.  But make sure your SPNs are right to start with, I had them wrong so that setting didn’t help on my first attempt.

  12. larsl says:

    Freddy,

    You were right. I had a problem with the authentication. Thanks for pointing me in the right direction 🙂

  13. Gerardo says:

    How can i do create a customer using the CREATE method with PHP and Dynamics NAV

  14. Rody says:

    Hi Freddy,

    Your code works very well, it helped me a lot. But now I need to Create a Customer instead of Read it.

    Can you help me?

    Thanks.

  15. navshae says:

    I have set the NTML as true.However I get the following error..its very urgent..pls help freddy…

    Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://localhost:7047/DynamicsNAV/WS/SystemService&#39; : Start tag expected, '<' not found in E:wampwwwnavconnect.php:185 Stack trace: #0 E:wampwwwnavconnect.php(185): SoapClient->SoapClient('http://localhos…') #1 {main} thrown in E:wampwwwnavconnect.php on line 185

  16. Jega says:

    Hi Navshae,

    It seems your curl request pads with some white space and the parser is expecting '<'.

    Please change the code here as follows in two places one at soapclient and another one at readbuffer:

    $response = trim(curl_exec($ch));

    This will remove uncessary white space before the '<'.

    I faced the same problem and it takes a while to find that.

  17. vasilis charalambous says:

    Hi,

    The php script looks great.Good Job., but haven't tried yet. Let's say the customer wants to have real time data of a php timesheet application with Navision.  Will it be secure to expose the Navision web service tier with a public ip address?the scenario is that the php application is hosted on a hosted service company and the navision database is in the company's internal network.    

    Or is it better to host the php application on the company's network in a DMZ and hire someone to secure the websever?

    the idea is to make customer's data secure and not to be published by the webservice.

    I have used NAV 2009 services with vb.net and c sharp and works great.

    Thanks,

    vasilis

    Navision and PHP developer.

  18. Valle says:

    Hi.

    Im doing a specialization-project on Magento and NAV integration.

    Im hoping to find a sample/tutorial on how to add database items to NAV by using php. Do you already have a blog about this or can anyone give me a hint from where to start?

  19. Jeffery Fernandez says:

    Hi Freddy,

    Thanks for  your tutorial. I can get the above examples to work, but have encountered a problem creating a new ItemCard record. I would much appreciate it if you could look at the problem I have addressed here: community.dynamics.com/…/45411.aspx

  20. Valle says:

    I am attempting to create a new ItemCard record in Dynamics NAV using PHP via webservices.

    I am able to create an empty  ItemCard record without any issues. However when I attempt to "update" the newly created record immediately afterwards, I get the following error:

    "Element "Key" in namespace "urn:microsoft-dynamics-schemas/page/itemcard" is missing from the message!".

    The ItemCard object param looks like this:

    ItemCard Object

    (

       [Key] => 300;GwAAAACJBTcwMDk1AAAAA [ VERY LONG STRING ] AAAA=6;2311140;

       [No] => 70095

       [Description] => Hello World

       [Inventory] => 25

       [Gen_Prod_Posting_Group] =>

       [Unit_Price] => 1000

    )

    Anyone know what I could be doing wrong? Is the format of the Key wrong? What should it be? Any help appreciated.

    P.S.

    This is Jefferys post, but i think that this will get more attention if this has been written into here.

    I happen to have a similar problem.

  21. Valle says:

    I am attempting to create a new ItemCard record in Dynamics NAV using PHP via webservices.

    I am able to create an empty  ItemCard record without any issues. However when I attempt to "update" the newly created record immediately afterwards, I get the following error:

    "Element "Key" in namespace "urn:microsoft-dynamics-schemas/page/itemcard" is missing from the message!".

    The ItemCard object param looks like this:

    ItemCard Object

    (

       [Key] => 300;GwAAAACJBTcwMDk1AAAAA [ VERY LONG STRING ] AAAA=6;2311140;

       [No] => 70095

       [Description] => Hello World

       [Inventory] => 25

       [Gen_Prod_Posting_Group] =>

       [Unit_Price] => 1000

    )

    Anyone know what I could be doing wrong? Is the format of the Key wrong? What should it be? Any help appreciated.

    P.S. this is Jefferys post copied from the page he is giving us. Hopefully this will get more attention when in here. I got similar problem.

  22. Jordi Navarro says:

    Hi Freddy,

    First of all, thanks for this post. It has helped me a lot and, now, I'm able to use Navision WebServices from PHP, wich, in turn, has also helped me to use PHP as a bridge to use Adobe Flex as a remote client.

    One thing I cannot get to work is: Wen you connect to a Codeunit WEBService that returns a XMLPort in one of its parameters, hou can you manage it from PHP?

    Here is an example:

    On Codeunit 50000, whe create a function:

    WSExportCustomer(codPrmCustomerNoFrom : Code[20],(codPrmCustomerNoTo : Code[20];VAR xmlCustomer : XMLport "WS Customer")

    recCustomer.SETFILTER("No.", '%1..%2', codPrmCustomerNoFrom, codPrmCustomerNoTo);

    xmlCustomer.SETTABLEVIEW(recCustomer);

    I cannot find a way to manage this.

  23. Jordi Navarro says:

    Hi, all,

    As I found the solution to the previous post, I respond myself so perhaps this can help to the rest of you.

    Regarding the Sample CodeUnit of the previous post, here you have a sample PHP script to use it:

    take into account that the name of the "published" CodeUnit is OperariosAlmacen

    require_once("ntlm/NTLMStream.php");

    require_once("ntlm/NTLMSoapClient.php");

    stream_wrapper_unregister('http');

    stream_wrapper_register('http', 'NTLMStream') or die("Failed to register protocol");

    $NoOP = "3039678";

    $Params = array();

    $Params["codPrmProdOrderNoFrom"] = $NoOP;

    $Params["codPrmProdOrderNoTo"] = $NoOP;

    $Params["xmlNoStockEntrada"] = null;

    $client = new NTLMSoapClient($baseURL . 'DE-FASE2/Codeunit/OperariosAlmacen');

    stream_wrapper_restore('http');

    $Result = $client->WSExportNoStockEntrada(&$Params);

    $Result is an object containing an array (or another object containing an array) of Objects

    In my case, to get wat's inside $Result, you have to do:

    $xmlNoStockEntrada = $Result->xmlNoStockEntrada;

    $ProdOrderLine = $xmlNoStockEntrada->ProdOrderLine;

    echo $ProdOrderLine[0]->ItemDescription;

    Hope this can help somebody.

  24. Kris says:

    Hi All,

    At first thanks Freddy for your tutorial. I really helped me. I, as some of you, had some problems with creating new card. I found solution so here is a code and I hope it could help others:

    First you must create a new class with name which is the same as your Web Service:

    class CustomerCard

    {

       public $CustomerCard;

    }

    Then you can add code to your script:

    $pageURL = $baseURL.rawurlencode($cur).'/Page/CustomerCard';

    $page = new NTLMSoapClient($pageURL);

    $customer = new CustomerCard;

    $customer->CustomerCard->Name = "Any Value";

    $customer->CustomerCard->Post_Code = '02-515';

    $page->Create($customer);

    That's all 🙂

    1. Amit says:

      Hello this create code is not working, while cretion step throws error “Fatal error: Uncaught SoapFault exception: [a:Microsoft.Dynamics.Nav.Service.WebMetadata.ServiceBrokerException] Evalution failed for field Type due to the following error: “OptionString not found.”.” can u please resolve this error

      1. FreddyDK says:

        The code was written for NAV 2009. A lot of things have changed since then (both with PHP and with NAV). The primary reason why things would be hard back then was, that NAV was only Windows Authentication (NTLM). Since then, NAV has become much simpler to use from other products – I will try to redo some articles especially focused on NAV on Azure (the gallery image).

  25. Hi , Creating new record issue says:

    Hi, I connected the webservices correctly , but when i put the data i got the error message :

    ———————————————

     [faultstring] => The Element  is expected by Min Occurs value: Once. Element received: .

       [faultcode] => a:Microsoft.Dynamics.Nav.Types.Exceptions.NavNCLXmlPortMetadataException

       [detail] => stdClass Object

           (

               [string] => The Element  is expected by Min Occurs value: Once. Element received: .

           )

    ———————————————-

    I am sending data like :

    —————————————————

    $arr['salesOrder'] = array("SalesLine"=>array("ItemNo"=> '1','Quantity'=> 1.00,'UnitPrice'=> 450.00));

    try {

    $results = $client->CreateSalesOrder($arr);

           echo $results->retrun_value;

       }

       catch (SoapFault $soapFault) {

          print_r($soapFault);

           echo "Request :<br>", htmlentities($client->__getLastRequest()), "<br>";

           echo "Response :<br>", htmlentities($client->__getLastResponse()), "<br>";

      }

  26. Yuan says:

    Dear Jega,

    I have same problem like Navshae. I found one at soapclient but another one i can't find.

    Can you give me a hint, thanks.. 🙂

  27. Marijn says:

    Thanks for this tutorial. Very helpful. It took me a little while to get everything hooked up, but eventually I got the standard CRUD methods working. So I can read, insert, update and delete records in NAV from my PHP Zend application. Which is awesome. However, there are still some things I have to figure out before I can actually implemend solutions based on NAV webservices. I hope someone can put me into the right direction for the remaining issues.

    1. How does the primary key mechanism work? Some tables do have 'No' field. Others have a 'Code' field. How do I know in advance what fieldname to use to retrieve a record? I think that somehow I have to extract this from the WSDL document. But I can't find this info anywhere.

    2. When I try to delete a Customer record which has dependend rows somewhere I get an error: "You cannot delete Customer 01445544 because it has ledger entries in a fiscal year that has not been closed yet.". That's not an error. My question is: How do you deal with return messages? I feel it has something to do which the _Result nodes, but I can't figure it out because the error is raised when calling the service the very first time. Maybe I can catch this error and deal with it, but I think that's going down the wroing road.

    I am happy to publish my finished class as soon as everything is working properly.

    Junior NAV / PHP developer, The Netherlands

  28. bourgba says:

    I'm having the same problem as navshae, I want to use your demo php code to test my Nav Webservice installations.

    Fatal error: SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://ws08-ifct-tst1:7047/DynamicsNAV/WS/SystemService&#39; : Start tag expected, '<' not found in

  29. Jack S says:

    How can i read the fields and type from the card as listed in the XML?

    Any help will be appreciated.

    Thanks

    <xsd:sequence><xsd:element minOccurs="0" maxOccurs="1" name="Key" type="xsd:string"/><xsd:element minOccurs="0" maxOccurs="1" name="Code" type="xsd:string"/><xsd:element minOccurs="0" maxOccurs="1" name="Name" type="xsd:string"/><xsd:element minOccurs="0" maxOccurs="1" name="Address" type="xsd:string"/><xsd:element minOccurs="0" maxOccurs="1" name="Address_2" type="xsd:string"/><xsd:element minOccurs="0" maxOccurs="1" name="Post_Code" type="xsd:string"/><xsd:element minOccurs="0" maxOccurs="1" name="City" type="xsd:string"/><xsd:element minOccurs="0" maxOccurs="1" name="Country_Region_Code" type="xsd:string"/><xsd:element minOccurs="0" maxOccurs="1" name="Phone_No" type="xsd:string"/><xsd:element minOccurs="0" maxOccurs="1" name="Fax_No" type="xsd:string"/><xsd:element minOccurs="0" maxOccurs="1" name="Contact" type="xsd:string"/><xsd:element minOccurs="0" maxOccurs="1" name="Location_Code" type="xsd:string"/><xsd:element minOccurs="0" maxOccurs="1" name="Customer_No" type="xsd:string"/></xsd:sequence>

  30. Senthilganesh says:

    Now a days such lot of hot stuffs blogs are coming for the notification. Its really interesting highly reputated concerns were doing such a blogs. Recently i read such a high stuff blog from the Custom web development company website http://www.cogzidel.com/blog/.

  31. Ravindranath Reddy says:

    This post really helped to get my service working to NAV Web Services from PHP..thank you so much……

  32. dsas says:

    The reason why you get a company name if there's one result and an array otherwise is down to PHP doing this by default. You can disable it with the options you pass into the SoapClient constructor

  33. Nie says:

    @dsas Could you elaborate that with an example? How would you pass the options into the SoapClient constructor? I could really use this. I'm tired of doing it over and over again in the code.

    Thanks!

  34. Kris says:

    Hi all,

    I have a problem while updating the record via Internet Explorer. I have error like this:

    Other user has modified "Table_Name" "Nr=CONST(Record_ID)"

    I do not have this error in Chrom and FireFox. Is anyone had that problem?

    Kind regard,

    Kris

  35. Irene says:

    PHP Fatal error:  SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://localhost:7047/DynamicsNAV/WS/SystemService&#39; : Start tag expected, '<' not found

    Error still exist even I changed to $response = trim(curl_exec($ch));

  36. Jack says:

    Allow NTLM connection in Navision configuration file. By default it is set to false.

  37. Arte says:

    There is a definitive problems with placing anything INTO NAV web services:

    Adding a bunch of data and sending via SOAP -> result is below:

    SoapFault exception: [a:Microsoft.Dynamics.Nav.Types.Exceptions.NavNCLXmlPortMetadataException] The Element is expected by Min Occurs value: Once. Element received: .

  38. Arte says:

    For everyone still struggling importing data into MS'NAV using PHP – I have a solution here:

    blog.artea.info/ms-nav-web-services-tofrom-php-receiving-and-sending-data/

  39. Abhijeet Kumar says:

    Hi,

    We have implemented exact PHP code but still getting below error..

    Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://localhost:7047/DynamicsNAV/WS/SystemService"&gt;

    We have set the authentication key but as we arent IIS experts, please advise on how to create SPNs.

    Regards,

    Abhijeet

  40. Abhijeet Kumar says:

    Marjin,

    Please share a document or steps how you connected to Navision using Zend framework. We are using the same but keep getting below error.

    PHP Fatal error:  SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://localhost:7047/DynamicsNAV/WS/SystemService&#39; : Start tag expected, '<' not found

    NTLM connection in Navision configuration file is properly configured.

    Regards,

    Abhijeet

  41. Manoj says:

    Hi Freedy,

    I connect my nav web service in my php but it's given error

    SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://localhost:7047/DynamicsNAVPMS/WS/SystemService&#39; : Start tag expected, '<' not found .

    Could you tell me where I went wrong?

    thanks in advance………

  42. Sam Smith says:

    Hi

    I'm trying to get this to work with NAV 2013 but getting the following error:-

    PHP Fatal error:  SOAP-ERROR: Parsing WSDL: Couldn't load from 'nav.haygrove.co.uk/…/SystemService

    Does 2013 work differently?

    Thanks

    sam

  43. Juan says:

    Hi Freedy,

    First of all thanks for your code and help.

    Now. I try your code and result is the common:

    Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from '192.168.4.18/…/SystemService& : Start tag expected, '<' not found in C:wampwwwsoapnavcreaped.php:163 Stack trace: #0 C:wampwwwsoapnavcreaped.php(163): SoapClient->SoapClient('http://192.168….') #1 {main} thrown in C:wampwwwsoapnavcreaped.php on line 163

    I try with all the comments of the users of this post but nothing cahnges.

    Could you help me?…

    Thanks and regards from Spain.

  44. Juan says:

    I find the mistakes, now I can connect to my NAV web service.

    First:

    Great error!!! I add the NTLM autentication code <add key="WebServicesUseNTLMAuthentication" value="true"></add> but few lines down, in the same configuration file I found another call to NTLM set to False!!!!!.

    Second:

    I must have some problem with autentication, becouse I install wamp server in my dynamics nav server and locally I can access. But remotely, from another PC i cant access.

    I hope this could help someothers.

  45. Juan says:

    To access remotely you must add delegation control in active directory

  46. Juan says:

    Anyone know how to Release_Sales_Document in PHP??

  47. PhDJ69 says:

    Thanks a lot Freddy ! This works for Dynamics AX 2009 too !

  48. Jesper says:

    This is a great page Freddy. Thank you

    I spend some time with Start tag expected, '<' not found .

    figured out at last I need to stop both webservices on server after changed  the WebServicesUseNTLMAuthentication setting and the start again. Just restart the services is not working

  49. Martin says:

    Thank you, you saved me a lot of time!

  50. Juan says:

    Hi!

    I have a web service to create sales order in NAV from Magento. All works fine but in some cases one of the items have no cross reference in NAV, then I get this error:

    ———————————————————————————————————————–

    Code: Select all

    Fatal error: Uncaught SoapFault exception: [a:Microsoft.Dynamics.Nav.Types.Exceptions.NavNCLDialogException] There are no items with cross reference: SMARTSC in C:wampwwwsoapgridpedanav.php:120 Stack trace: #0 C:wampwwwsoapgridpedanav.php(120): SoapClient->__call('Update', Array) #1 C:wampwwwsoapgridpedanav.php(120): NTLMSoapClient->Update(Object(stdClass)) #2 C:wampwwwsoapgridcrearpednav.php(112): crearpedidonav(Array, Array, 3, 'http://localhos…') #3 {main} thrown in C:wampwwwsoapgridpedanav.php on line 120

    ———————————————————————————————————————–

    I loose this new sales order in NAV, but this is not the problem, the real problem is that the nav web service become inaccesible. If I try to create another sales order (in this case with all cross references ok) I get the next error, like the service is blocked:

    ———————————————————————————————————————–

    Code: Select all

    Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't find <definitions> in 'http://localhost:7047/DynamicsNAV/WS/Page/Sales_Order&#39; in C:wampwwwsoapgridpedanav.php:34 Stack trace: #0 C:wampwwwsoapgridpedanav.php(34): SoapClient->SoapClient('http://localhos…') #1 C:wampwwwsoapgridcrearpednav.php(112): crearpedidonav(Array, Array, 2, 'http://localhos…') #2 {main} thrown in C:wampwwwsoapgridpedanav.php on line 34

    ———————————————————————————————————————–

    If I use Internet Explorer to navigate to the web service URL 'http://localhost:7047/DynamicsNAV/WS/Page/Sales_Order&#39; I can see the web service definition and all become working again. I can use the web service to ceate new sales order without problem.

    The quetions is… Why the service become unavalilable afther an error?… How can I solve or restart the service with code in php?

    Note: In windows service configuration and services tab I have configured the service to restart in case of errors.

    Resume:

    All right creating sales order –> Error with not found cross reference in one new sales order –> web service become inavailable –> Cant create new sales order –> Navigate with browser to web service url –> All work right again.

    Thanks!!

  51. Ken Muturi says:

    I'm getting this error below

    Fatal error: Uncaught SoapFault exception: [Client] SoapClient::SoapClient(): Invalid parameters in

    Please help 🙁

  52. Jonathan Karimi says:

    Your code works. I jus have to get my log in credentials right. I thought i did not need 'domainuser' coz i am on a work group but after i serched my log in account , i found out that all accounts have that format.

    Am also using WAMP server and the code works

  53. Sam 5 says:

    Hi,

    In case someone also has this issue

    SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://xxxxxxxxxx:1234/DynamicsNAVPMS/WS/SystemService&#39; : Start tag expected, '<' not found .

    Here is how I solved it,

    First I followed the steps mentioned above,

    -> Allow NTLM connection in Navision configuration file. By default it is set to false.

    ->add the NTLM autentication code <add key="WebServicesUseNTLMAuthentication" value="true"></add>

    Double check that a few lines down, in the same configuration file there isn’t another call to NTLM set to False.

    ->After changing the WebServicesUseNTLMAuthentication setting, stop webservices on server and start again. Just restarting the services does not working

    After that didn't work (giving me the same error), I double checked the authentication, and that worked for me

    // Authentification parameter

    class MyServiceNTLMSoapClient extends NTLMSoapClient {

     protected $user = 'xxxxxxxxxx';

     protected $password = 'xxxxxxxxxx';

    }

    class MyServiceProviderNTLMStream extends NTLMStream {

     protected $user = 'xxxxxxxxxx';

     protected $password = 'xxxxxxxxxx';

    }

    stream_wrapper_unregister('http');

    // we register the new HTTP wrapper

    stream_wrapper_register('http', 'MyServiceProviderNTLMStream') or die("Failed to register protocol");

    // so now all request to a http page will be done by MyServiceProviderNTLMStream.

    // ok now, let's request the wsdl file

    // if everything works fine, you should see the content of the wsdl file

    // Initialize Soap Client

    $baseURL = 'xxxxxxxxxxxx:1234/LS_201554321/WS/Services';

    $client = new MyServiceNTLMSoapClient($baseURL);

    hope this helps someone else

    1. monica says:

      after all the integration i am getting soapfault like :
      “Type: SoapFault
      Message: SoapClient::SoapClient(): Invalid parameters” please help me to solve this problem.

  54. KeepUp says:

    Some one have this error?
    PHP Fatal error: SOAP-ERROR: Parsing WSDL: Couldn’t load from ‘http://192.168.1.248:8047/DynamicsNAV/WS/XXXX/Page/WS_List_User_Work_Center’ : Document is empty

    Can you give me an hint?

    Thanks,
    Jacopo

  55. Dirk says:

    Hey Freddy,

    “Note that is return value is an array if there are multiple companies, but a company name if there is only one. I have NO idea why this is or whether I can write the code differently to avoid this.”

    Just pass array(‘features’ => SOAP_SINGLE_ELEMENT_ARRAYS) to avoid this:)

    Dirk

  56. push says:

    The code helps in solving authentication problems

  57. Jelle De Loecker says:

    All I’m getting is a “Document is empty” response.
    Loging through the browser works, but through PHP fails:

    PHP Fatal error: SOAP-ERROR: Parsing WSDL: Couldn’t load from ‘http://9.9.9.9:7057/TestWebService/WS/Bla/Services’ : Document is empty
    in /home/skerit/projects/navision.php on line 199
    PHP Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn’t load from ‘http://9.9.9.9:7057/TestWebService/WS/Bla/Services’ : Document is empty
    in /home/skerit/projects/navision.php:199
    Stack trace:
    #0 /home/skerit/projects/navision.php(199): SoapClient->SoapClient(‘http://9.9….’)
    #1 {main}
    thrown in /home/skerit/projects/navision.php on line 199

  58. bdes says:

    Hi, this is an awesome blog and nice method, however despite being able to install it on many servers (locally and remotely) I can’t use it on Nav running from Azure. I can access webservices through the browser without any hassle, but NTLM just doesn’t work. Would that be SSL problem (web service is on HTTPS) or Azure? I tried to modify the code to add ssl certificate but no luck 🙁

  59. Matej Svajger says:

    Hello!

    I’ve made a package you can use via composer to make this painless.
    https://github.com/matejsvajger/ntlm-soap-client

    This article helped a lot!

    Also there is some weird caching going on in php, if your request fails on the first time, then the second run won’t even perform a request (skip the http stream replacement or SoapClient->__doRequest method) – and will fail automatically. To avoid it append a random query string to your web service url like ‘http://localhost:7047/DynamicsNAV/WS/SystemService?v=0.1’ and save yourself a lot of headaches 🙂

Skip to main content