An Existing Purpose-Built Website, Synchronizing the Information
If you’re lucky, you will find a website solution that is purpose built for the problem you’re solving. A retail system is a good example. In this scenario you just need to have a mechanism to synchronize the data, and often not in real-time. For example, prices can be updated in a batch process nightly from NAV into a retail system, and sales information can be grabbed from that system and put into sales journals and posted in Dynamics NAV. In this scenario you only need to custom build the synchronization component. This component could connect to either your business web services or do regular updates from a landing area in your Dynamics NAV database (for example writing sales into the sales journal, and potentially reading current pricing or inventory from Dynamics NAV).
An Existing Custom Website, That Now Needs to Integrate Some NAV Data with Existing Data
Sometimes you’ve got a website with a database that already exists, and you just need to grab some of the data and merge it with some other information.
If you need to merge the data, and the data does not need to be real-time then your integration option looks similar to the 3rd party component web site.
An Internal Website, or a Website that Needs Real-time Information
If it’s an internal website, or need real-time data then you can connect directly the Dynamics NAV SQL database or to the Dynamics NAV web services.
There are many variations of the above. For example, you might want database replication to keep your NAV data available and not have web usage introduce risk or load on your company operations.
Choosing the Integration Interface to Connect with NAV
There are several NAV interfaces, but you’ve really got two main options. RTC business web services (Dynamics NAV pages or CodeUnits exposed as business web services), or direct to SQL server. The best choice will really depend on your architecture, which is also affected by your licensing.
2009 Web Services, AJAX > RTC Web Services
If you’re using NAV 2009 you have the option of using the RTC web services. These web services are really meant for SOA integration, however you could just expose the RTC web services directly over the Internet and then have a completely AJAX driven website connect to that, however the web service requires you to be authenticated against Active Directory. This has a few implications:
- Licensing (again). Every user would need windows CAL and a dynamics NAV C/AL. This option is fine for your existing Dynamics NAV users as that license fee would already have been paid, but it makes it more costly to allow access for your customers or vendors. It’s not an option at all for anonymous logins.
- Kerberos double (or more) hop. Having gone through this several times it’s doable, however be aware that some IT departments will not allow web accessible computers to delegate authentication, which is a key step in configuring double-hop to work properly. Determine now before you start whether this is a possible deployment scenario, because sometimes it’s a showstopper.
Another issue with the AJAX Dynamics NAV Web service option is that the web services provided do not work out of the box with the two popular AJAX frameworks JQuery or EXTJS, which would require several JavaScript wrappers. In 2013 that should change with the ODATA option that will be available.
2009 Web Services, but with Your own Custom Decorators and Controllers on Top
Dynamics NAV 2009 web services are WCF based, which makes it very simple to connect to from ASP.Net based systems. This also provides the option to have your web site exposed with it’s own custom forms based authentication, while still connecting to NAV as a single application user (check your licensing options before you do this). This makes it easy to execute NAV business logic from within your custom website, and provide access to data.
Direct to SQL Server
If you’re using Dynamics NAV 5 or earlier then web-services aren’t available as an option, and you will often need to just connect to SQL server directly.
Even if you’re on 2009 or later, the downside to using the NAV web services is that it is not the most efficient communication available. For performance-minded applications this is not often a solution as you’ll have your website data layer, making an HTTP call to the web services, passing noisy XML data back and forth, and having that XML data serialize and de-serialize both on the side of Dynamics NAV and your custom website.
Your challenges with the direct to SQL Server option are:
- No business logic is available.
- The table naming convention of prefixing SQL server tables “CompanyName$” will make it more difficult to develop and deploy, and can also cause problems with newer frameworks such as Ruby on Rails, or MVC.Net
In a future blog post we’ll show how to use a new framework (MVC.Net) to connect to SQL server directly for the situations where the Dynamics NAV web services are not an option, and get around the table-naming problem.
Using Services
define('USERPWD', 'domain\user:password'); 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; } }
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"; } }
// 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)
相关推荐
Learning Continuous Integration with Jenkins 英文azw3 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除
Robust Cloud Integration with Azure by Mahindra Morar English | 22 Mar. 2017 | ASIN: B01KK6H3J4 | 696 Pages | AZW3 | 44.92 MB Unleash the power of serverless integration with Azure About This Book ...
Take your skills to the next level with Dynamics NAV by implementing all the latest and advanced features Get a comprehensive coverage of how the NAV system can be implemented and maintained to get ...
This book, Learning Continuous Integration with Jenkins Second Edition, serves as a step-by-step guide to setting up a Continuous Integration, Continuous Delivery, and Continuous Deployment system ...
Python Continuous Integration and Delivery: A Concise Guide with Examples By 作者: Moritz Lenz ISBN-10 书号: 1484242807 ISBN-13 书号: 9781484242803 Edition 版本: 1st ed. 出版日期: 2018-12-29 pages ...
It is being used for anything from small and quickly constructed add-on functions written either to fluidly experiment with something new or to accelerate computing by replacing an R function with its...
Learning Continuous Integration with Jenkins - Second Edition: A beginner's guide to implementing Continuous Integration and Continuous Delivery using Jenkins 2 Key Features Understand the concepts ...
Enterprise Integration with Ruby
Learning Continuous Integration with Jenkins(2nd) 英文mobi 第2版 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书
Networkers2009:BRKDCT-2868 - Network Integration of Server Virtualization with LAN & Storage
SAS/ACCESS Interface to Amazon Redshift 31DEC2019 SAS/ACCESS Interface to Aster 31DEC2019 SAS/ACCESS Interface to DB2 31DEC2019 SAS/ACCESS Interface to Greenplum 31DEC2019 SAS/ACCESS Interface to HAWQ...
In addition, “The 2014 HL7 Interface Technology Survey Results” show that Mirth Connect is one of the fastest growing healthcare messaging platforms due to its open source paradigm, and robust ...