NAV Web Service and PHP

I wanted to replace MySQL with NAV Web Service as a data source for my PHP web site.  I started to look around and found all I needed in Freddys Blog.  First post is about changes in authentication method of the web service, the later post displays the code needed to connect to the web service with php.

I have an php web on my Windows Home Server and needed to activate two more extensions to get things working.

Here are the php files that I used – PHP consume NAV Web Service

Example on using NAV Web Service in NAV C/Side

Some of our clients are using LS Retail.That solution supports stand-alone POS terminals that are running Microsoft Dynamics NAV.  It is therefore easy to allow these terminals to be used also as a punch clock.

This punch clock starts up a background process to handle synchronization via web services.  Attached is a demo c/side code on how the web services are consumed.

SyncEmployees

Example on using NAV Web Service in Visual Studio vb.net

This is using the web service in my previous post.  In Visual Studio I start by adding the web reference.  Select Project -> Add Service Reference

Then select Advanced…

Then Add Web Reference…

Where I insert URL encoded string for the published codeunit including the company name.

I created a form with a listbox object and a button.  I used this code to insert all employee no’s into the listbox.
[code htmlscript=”false” lang=”vb”]Public Class Form1
Dim ClockID As String
Dim Success As Boolean
Dim DefCred As Boolean
Dim ResponseMessage As String
‘The Web Service
Dim NAVPunch1 As New WebService.NAVPunch
‘New set of credentials
Dim User As New System.Net.NetworkCredential

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles MyBase.Load
If DefCred Then
NAVPunch1.UseDefaultCredentials = True
NAVPunch1.Url = ""
Else
User.Domain = ""
User.UserName = ""
User.Password = ""
NAVPunch1.Credentials = User
NAVPunch1.Url = ""
End If
ClockID = "{4A212826-CAF3-4E3C-9D97-6923A692A209}"

End Sub
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
‘ Get Employee List
ResponseMessage = ""
ListBox1.Items.Clear()
Dim EmployeeList As New WebService.EmployeeList
Try
Success = NAVPunch1.GetClockEmployees(ClockID, _
EmployeeList, _
ResponseMessage)
CheckBox1.Checked = Success
TextBox1.Text = ResponseMessage
If Success Then
For Each Employee In EmployeeList.Employee
ListBox1.Items.Add(Employee.No)
Next
End If
Finally
End Try
End Sub
End Class[/code]

Creating Web Services in NAV 2009

I have been working on NAV Time Registration and the solution is almost ready.  The last step was to create a web service that supports stand-alone punching clocks, both in .net c# and also as a NAV client.

The web service is a standard codeunit with functions.  I make sure the functions that are not to be published have the Local property set to Yes.

Using XMLport in web services requires a few parameter changes.  First I include them in the function parameters.  I use a boolean parameter in Return Value as a success flag.

Then in XMLport properties I change direction to export, change format to XML and select to use default namespace.

The C/Side code to answer this web service is.
[code htmlscript=”false”]IF NOT ValidateClockID(ClockID,ResponseMessage) THEN BEGIN
InsertLog(ClockID,Log.GetEmployeeList,FALSE,ResponseMessage,”);
EXIT(FALSE);
END;

IF NOT CreateEmployeeBuffer(EmployeeBuffer,ResponseMessage) THEN BEGIN
InsertLog(ClockID,Log.GetEmployeeList,FALSE,ResponseMessage,”);
EXIT(FALSE);
END;

EmployeeList.SetEmployeeList(PunchClock.Code,EmployeeBuffer);
ResponseMessage := Text033;
InsertLog(ClockID,Log.GetEmployeeList,TRUE,”,”);
EXIT(TRUE);[/code]
Then finally I run form 860, Web Services and add a line for this web service to be published.

Next post is a demonstration on how to use this web service.  I used Freddys multiple service tier post in my developement enviroment to setup NAV services.

 

File download with RTC

My earlier post on File Download used the responsestream property of WinHTTP. On my latest project I needed to use Windows Authentication on my website and found out that I needed to create the WinHTTP automation on client level to login with the current user. This also means that I cannot use built in streaming functions to download the file. Instead I used ADOStream function to download the file and in the example that follows I am saving the file to the temporary directory for the current user.
[code htmlscript=”false”]DownloadFile(URL : Text[1024]) FileName : Text[1024]
IF ISCLEAR(WinHTTP) THEN
CREATE(WinHTTP,TRUE,TRUE);

WinHTTP.open(‘GET’,URL,FALSE);
WinHTTP.send(”);

IF WinHTTP.status <> 200 THEN
ERROR(Text023,WinHTTP.status,WinHTTP.statusText);

FileName := WinHTTP.getResponseHeader(‘Content-Disposition’);
IF STRPOS(FileName,’filename=’) = 0 THEN
FileName := ”
ELSE BEGIN
FileName := COPYSTR(FileName,STRPOS(FileName,’filename=’) + 10);
IF ISCLEAR(ADOStream) THEN
CREATE(ADOStream,TRUE,TRUE);

IF ADOStream.State = 1 THEN
ADOStream.Close;

ADOStream.Type := 1; // adVarBinary
ADOStream.Open;
ADOStream.Write(WinHTTP.responseBody);

IF ISCLEAR(FileSystem) THEN
CREATE(FileSystem,TRUE,TRUE);

FileFolder := FileSystem.GetSpecialFolder(2);
FilePath := FileFolder.Path;
ADOStream.SaveToFile(FilePath + ‘\’ + FileName,2);
FileName := FilePath + ‘\’ + FileName;

ADOStream.Close;
END;

CLEAR(WinHTTP);[/code]
Where my variables are

FileSystem – Automation – ‘Windows Script Host Object Model’.FileSystemObject
FileFolder – Automation – ‘Windows Script Host Object Model’.Folder
WinHTTP – Automation – ‘Microsoft XML, v6.0’.XMLHTTP
ADOStream – Automation – ‘Microsoft ActiveX Data Objects 2.8 Library’.Stream
FilePath – Text[1024]

SMS from NAV

In modern ERP solutions the system should be able to send SMS to employees, customers and vendors.  The phone service provider Síminn in Iceland offers a web service interface for applications to send SMS.

Attached is a source code that uses this web service to send SMS.

SMS Source Code

Download a File

In Dynamic NAV it is possible to use the Automation “‘Microsoft XML, v6.0’.XMLHTTP” to download files.  The code would be
[code]IF ISCLEAR(WinHTTP) THEN
CREATE(WinHTTP,TRUE,FALSE);

WinHTTP.open(‘GET’,URL,FALSE);
WinHTTP.send(”);

IF WinHTTP.status <> 200 THEN
ERROR(Text003,WinHTTP.status,WinHTTP.statusText);

TempFile.CREATE(TempFileName);
TempFile.CREATEOUTSTREAM(OutStr);
InStr := WinHTTP.responseStream;
COPYSTREAM(OutStr,InStr);
TempFile.CLOSE;[/code]
Where Text003 is “Status error %1 %2”

The URL will be downloaded to the filename “TempFileName”

Add Namespaces to outgoing XML

The tax authority in Iceland are using Soap web services.  I have built XML Ports in NAV to create the request XML and another one to read the response XML.

I already wrote about using stylesheet to strip namespaces from the incoming XML before passing it to the XML Port.  I previously just added namespaces to the outgoing XML with attributes in the request XML Port.  This does not work in Role Tailored Client.

The solution was to remove all the namespaces attributes from the request XML Ports and create a function to add namespaces to the XML before passing it to the web server.  This work both in Classic Client and in Role Tailored Client.

AddNameSpaces source code

Dynamics NAV and Soap Services

Soap Web Services return XML with name spaces.  You need to remove the name spaces before you can use XMLPort to read the answer.  Microsoft has supplied a solution to this problem by applying Stylesheet to the XML before it is read by the XMLPort.  I added to that Stylesheet a few lines to remove the Header section of the XML.

Attached is a working example that queries a bank for a given bank account and registration number.

Here is the source code.