Record Links in NAV 2009 R2

I made a function that collects all the record links from the documents related to a customer ledger entry or a vendor ledger entry.  I then display the list or record links and offer the user the change to open the links or email them.

This all worked just fine in my Classic Client but in the Role Tailored Client the page gives me a metadata error.  I asked Microsoft and got an answer from Lars Lohndorf-Larsen.

I have been in contact with development and they say that this is unfortunately a restriction in NAV2009. It is not possible to use “Record Link” as Source Table on a page.
“Record Link” is a special table which gets (re)built dynamically. A page expects a normal table and will implicitly compile the underlying table. But this particular table does not have usual metadata that the page expects, so it fails.
In NAV2013 it works because this table was redesigned.

This means that I will have to use the Record Link table as a global variable instead of using it as a source table.  That is what I will do.

Use WSDL and dotnet interop in the Role Tailored Client

I have been working with the dotnet interop and consuming soap web services.  I wrote about a dotnet interop based way to communicate with soap web services in a previous blog but now I want to demonstrate another way that requires just a few lines of code.

I would like to find a web service that is open so everyone can do their own testing.  I found a web service that will look up a country by an IP address.

The first step is to start Microsoft Visual Studio and create a new project.  The language that you choose is not important.

I delete Class1.cs.  Then go to Project menu and Add Service Reference.  Click Advanced… and Add Web Reference…  Look in my previous blog for more details.

I paste the web service URL in to Visual Studio and select a name for the web reference.

I go to Project and GeoIPService Properties to make sure that I am using .NET Framework 3.5 and I choose to create my own key to sign the class.  I also like to add details to the Assembly Information…

I go to Signing and create a new key file with my own password.

Then I save the project and select Build and Build GeoIPService.  In the solution folder I will now find the GeoIPService.dll file.  This file I copy to my Classic Client Add-ins folder.  I start the Classic Client and create a new Codeunit.  I will then add a dotnet global variable with my new class.  I create a variable both for GeoIPService and for GeoIP.

I the need to choose if I would like the service to be run on the client or on the server.  If I choose to run on the client then I need to copy the class file to Role Tailored Client Add-ins folder for every user.  If I choose to run on server I copy the class file to the service Add-ins folder.  I selected to run on server since I do not have to supply my domain user name or any certificates to the service.

The code in the Codeunit is as follows

[code]
GeoIPService := GeoIPService.GeoIPService;
GeoIPService.Url := ‘http://www.webservicex.net/geoipservice.asmx’;
GeoIP := GeoIPService.GetGeoIP(‘93.95.74.198’);
MESSAGE(
‘Return Code: %1\IP Address %2\Country Name: %3\Country Code: %4’,
GeoIP.ReturnCode,
GeoIP.IP,
GeoIP.CountryName,
GeoIP.CountryCode);[/code]

I then start the codeunit in my Role Tailored Client with the Run Object Page that Microsoft supplied in their blog.

Attached is the codeunit, the class library and the Run Object Page from Microsoft.

GeoIPService

NAV Timer DotNet Addin

Freddy supplied the code to build a timer to be used in pages in the Role Tailored Client.  His blog entry about the timer is here.

Some of the comments show that developers have had the same problem that I ran into.  I change the code just a little bit.  Freddy’s code is

[code lang=”csharp”]public override string Value
{
get
{
return base.Value;
}
set
{
base.Value = value;
if (!int.TryParse(value, out interval))
{
interval = 0;
}
interval = interval * 100;
if (timer != null && timer.Interval != interval)
{
timer.Interval = interval;
count = 0;
if (interval == 0)
timer.Stop();
else
timer.Start();
}
}
}
[/code]

I moved the line “timer.Interval = interval;” down four lines.

[code lang=”csharp”]public override string Value
{
get
{
return base.Value;
}
set
{
base.Value = value;
if (!int.TryParse(value, out interval))
{
interval = 0;
}
interval = interval * 100;
if (timer != null && timer.Interval != interval)
{
count = 0;
if (interval == 0)
timer.Stop();
else
timer.Interval = interval;
timer.Start();
}
}
}
[/code]

and the problem was solved.

NAV Timer Add-in

A DotNet Interop Soap Web Request

I am currently working on a solution that requires a Dynamics NAV client to communicate with Dynamics NAV web service.  This I have done before with the classic client and have used automation objects for the job.  Now I wanted to do this with dotnet only objects in the Role Tailored Client.  Took some time to put all things together but here it is.  This version is running the request from the client.

 

DropDown in RTC

In the table designer the fields that appear in the drop down list are defined.  For example the Customer table.

I found a feedback in Microsoft Connect and added a few comments to that.  What I would like the drop down window to be able to do is;

  • remember the last position and default to that one
  • allow multi select that will result in a filter

I would love this to be applied to both pages and the report “Show results:” area.

 

NAV 2013 and ClickOnce Install

I have installed NAV 2013 on a Windows 2008 Server.  Everything is working fine and it is time to create the OneClick installation source.  I followed the documentation from Microsoft.  Make sure that when you install NAV 2013 to select ClickOnce Installer Tools.

I first found that the SDK needed for the mage.exe command is not available on the server.  I downloaded and installed Microsoft Windows SDK for Windows 7 and .NET Framework 4 from Microsoft.

I created the folder C:\inetpub\wwwroot\NAV2013Beta as the source for deployment and the folder C:\inetpub\wwwroot\NAV2013Beta\Deployment\ApplicationFiles for the application.  I created a read only share for the folder NAV2013Beta.  I copied everything from the folder C:\Program Files (x86)\Microsoft Dynamics NAV\70\RoleTailored Client to this folder.

I found the folder C:\ProgramData\Microsoft\Microsoft Dynamics NAV\70 and copied the ClientUserSettings.config file to my C:\inetpub\wwwroot\NAV2013Beta\Deployment\ApplicationFiles folder.  First I made sure that the server was not set to localhost but to the network server name.

I found the folder C:\Program Files (x86)\Microsoft Dynamics NAV\70\ClickOnce Installer Tools\TemplateFiles and copied all files to my C:\inetpub\wwwroot\NAV2013Beta folder, selecting to merge the Deployment folder.

Next I opened Command Prompt and typed

I got the following errors

Decided to remove the Development Client and only install the Role Tailored Client and restarted the process and got a better result.

Continuing in the command prompt

I change the Name to identify the installation

I changed the description

and I needed to change the Start Location

Again, I saved the file selecting not to sign it.

In my \\nav2013\NAV2013Beta folder I used Word to create the Software License Terms for my company and saved is as Rich Text Format as PartnerSolutionLicense.rtf.

Then I opened the NAVClientInstallation.html file in Notepad and removed the TODO both for the text and for the link.

Next I tried the installation by browsing to the folder \\nav2013\NAV2013Beta on a Windows 2008 Remote Desktop Server and double clicking on NAVClientInstallation.html file.  After a few click I had my NAV 2013 Beta up and running.

Client Temporary Path

In one of my solutions I create a lot of Excel and PDF documents.  All these documents are stored in BLOB fields and then downloaded to the client computer temporary folder and opened for the user.

Every time I use the ClientTempFileName function in Codeunit 419 a file is being created in the client computer temporary folder and that file is not deleted until the Role Tailored Client is closed.

Since the user is creating temporary files his whole workday I decided that a single instance codeunit would be a better way to store information about the client and server temporary file paths.  I created codeunit 50060 and two functions; GetClientTempPath and GetServerTempPath.
[code htmlscript=”false”]OBJECT Codeunit 50060 Application Temp Path Mgt.
{
OBJECT-PROPERTIES
{
Date=27.03.12;
Time=16:11:00;
Modified=Yes;
Version List=Dynamics.is;
}
PROPERTIES
{
SingleInstance=Yes;
OnRun=BEGIN
END;

}
CODE
{
VAR
ThreeTierMgt@1200050000 : Codeunit 419;
ClientTempPath@1200050001 : Text[1024];
ServerTempPath@1200050002 : Text[1024];

PROCEDURE GetClientTempPath@1200050000() : Text[1024];
BEGIN
IF ClientTempPath = ” THEN
ClientTempPath := ThreeTierMgt.Path(ThreeTierMgt.ClientTempFileName(”,”));
EXIT(ClientTempPath);
END;

PROCEDURE GetServerTempPath@1200050001() : Text[1024];
BEGIN
IF ServerTempPath = ” THEN
ServerTempPath := ThreeTierMgt.Path(ThreeTierMgt.ServerTempFileName(”,”));
EXIT(ServerTempPath);
END;

BEGIN
END.
}
}[/code]
The Source is here, Application Temporary Path

 

Data Visualization Control not found

Just created a chart for a customer and added it to the customized role center.  The customer got a permission error when opening the client as there is no permission to read the table Chart no. 2000000078.  Added read permission to that table to the user role and the client started.  The next error was that the data visualization control was missing on the client machine.

A quick search pointed me to this download link.  After installing and restarting the client everything is working as it should be.

Using OpenXML to create an Excel Document

In one of my projects I needed to create a complex Excel document from Dynamics NAV.  I did this by using COM automation in the same way that Microsoft is doing in the Excel Buffer table no. 370.  The problem is that this is dead slow.  It could take up to two minutes to create a single Excel document on the Role Tailored Client.

I saw in Kauffmann’s blog that it is possible to use OpenXML on the server side to create the Excel document.  Great blog and a big help.  The same Excel document is now created in under two seconds.

As I started the batch to create the OpenXML Excel documents I received an error: “hexadecimal value 0x1F, is an invalid character”.  I was inserting an invalid character into the XML.  I did a quick search and found a solution, I needed to filter the data through a white list.  Here is my AddCell function:

 

The line

 

is used to clean the string that is passed to the XML.

The GetEnumValue function is

 

When constructing the OpenXML dotnet object I also construct the white characther check object.

 

Attached is the Add-in needed on the server side.

XMLCharWhiteList Add-in

 

 

WinHTTP and RTC Client

I have been using the automation ‘Microsoft XML, v6.0’.XMLHTTP to communicate with web services and web sites.  I have been experiencing a problem with this automation when running in Role Tailored Client.  The solution has been to use the automation ‘Microsoft XML, v6.0’.ServerXMLHTTP when running in the service tier.
[code htmlscript=”false”]IF ISSERVICETIER THEN BEGIN
IF ISCLEAR(WinHTTPServer) THEN
CREATE(WinHTTPServer,TRUE,FALSE);
WinHTTPServer.open(‘GET’,URL,FALSE);
WinHTTPServer.send(”);

IF WinHTTPServer.status <> 200 THEN
ERROR(Text007,WinHTTPServer.status,WinHTTPServer.statusText);

DOMDocument.load(WinHTTPServer.responseXML);
CLEAR(WinHTTPServer);
END ELSE BEGIN
IF ISCLEAR(WinHTTP) THEN
CREATE(WinHTTP,TRUE,FALSE);
WinHTTP.open(‘GET’,URL,FALSE);
WinHTTP.send(”);

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

DOMDocument.load(WinHTTP.responseXML);
CLEAR(WinHTTP);
END;[/code]
Where Error string Text007 is “Status error %1 %2”.