Category Archives: Microsoft Dynamics NAV 2017

Cumulative update CU 51 for Microsoft Dynamics NAV 2017 has been released

For a complete list of updates please take a look at Microsoft Support: https://support.microsoft.com/en-us/topic/released-cumulative-updates-for-microsoft-dynamics-nav-2017-99f042ca-81ed-9fd5-2645-75fa9590dfd1

The CU only contains only minimal improvements. Depending on the localization other objects can be fixed. On platform level the fixes are really minimal:

Bron: https://support.microsoft.com/en-us/topic/cumulative-update-51-for-microsoft-dynamics-nav-2017-build-30443-887d362a-9dc7-4cac-a8e9-81ff9a57b9bc

The RecordID Datatype

When you declare a local or global var you could specify the RecordID datatype in Microsoft Dynamics NAV like this:

C/AL Locals Window

So what does this data type exactly holds? I was curious as ever to found out and started reading Microsoft Docs. This data type contains the table name and primary key values of a record in a certain table. Not a surprise (for you) but for me it was: you can store a recordID in a field with datatype RecordID also. When you view the recordID field contents in the client it’s not visible:

RecordID value displayed in the Windows Client

I’m curious what it exactly holds so I started writing some code in a codeunit and runned it:

RecRef.OPEN(DATABASE::Customer);
RecRef.FINDLAST;
RecID := RecRef.RECORDID;
MESSAGE('%1',RecID);

The code above opens the customer table, finds the last record and displays a message with the contents of the RecID variable.

View the current timestamp of a record

Recently I was experimenting with code and made an error by accident. Experimenting with C/AL statements or datatypes makes me understand code and functionality better. I specified by accident RecordRef.FIELD(0). This field number doesn’t exist you think. But it gave me a result:

This code:

RecordRef.OPEN(18);
RecordRef.FINDFIRST;
FieldRef := RecordRef.FIELD(0);
MESSAGE(FORMAT(FieldRef.VALUE));

Results in:

Message in Windows Client

So I started to search for some answers. Quickly found out it was the timestamp of the record! In one of my early Nav days (already six years now) as a consultant I already knew and saw that this was a physical column in SQL for each row in a table.

The physical column timestamp is visible in SQL Server but not in Microsoft Dynamics Nav

Nav uses it for versioning as an internal mechanism so you cannot view the value by default, even if you are running the table directly from the Development Environment. There is another possibility explained by Microsoft by adding a BigInteger field to an Nav table and then select the SQL TimeStamp property:

But the code earlier mentioned accomplishes the same thing without creating an extra field. I thought it was worth sharing so maybe it will be usefull for someone.

Your program license has expired.

Recently a customer of us received a message that their license has expired. This message is shown when you connect to an Nav database from the Development Environment. The message looks similar like this:

Your program license has expired

Textual: Microsoft Dynamics NAV Development Environment
Your program license has expired.

However the customer wants to update the license with a fresh one but how to accomplish this because you can’t connect to your Nav database? The very first thing to do is to not connect to the database so that you won’t receive the message. Steps:

  • Open Development Environment and don’t connect to a database
  • Go to Tools > License Information and press Change.
  • Now select a new valid license.
  • Now connect to your Nav database and Upload the fresh license into your database.

Note: in order for the license to be effective in the Windows or Web client you need to restart all servicetiers that are connected to your corresponding database.

Your program license does not permit more users to work simultaneously

Today I was asked by a customer how many times the maximum concurrent users license limit was reached. Interesting question in my opinion. Why? Because I reminded in the past I saw an Application Log warning event about this but I wasn’t sure. So I did some research in my lab Nav 2017 environment. First I reproduced the error by logging on a multiple users. The license limit was reached. Message:

Your program license does not permit more users to work simultaneously. Wait until another user has stopped using the program. Contact your system administrator if you want to allow more simultaneous users on your system
Warning the user will see when the Nav License limit has been reached.

Full warning text: Your program license does not permit more users to work simultaneously. Wait until another user has stopped using the program. Contact your system administrator if you want to allow more simultaneous users on your system

We all probably know this message, right? If not you now know. Now I checked the application logs on the service tier machine and yes… the above message has also been logged on the server in the application log:

Server instance: NST100TestCronus
Category: License
ClientSessionId: 7b6b163b-5c54-471f-b4b9-1809614cb7a3
ClientActivityId: bec67c3b-9fe6-43aa-b7be-a41dd02d2d53
ServerSessionUniqueId: ad7a2e4a-4a96-4fc8-b098-58ede70f4571
ServerActivityId: 4245b653-fb6d-4288-aaa2-2f284c1a3465
EventTime: 11/05/2019 14:44:19
Message (NavLicenseViolationException): Your program license does not permit more users to work simultaneously. Wait until another user has stopped using the program. Contact your system administrator if you want to allow more simultaneous users on your system.
ExceptionStackTrace:

CallerStackTrace:
at Microsoft.Dynamics.Nav.Runtime.NavLicenseValidator.ValidateUsersHasAnActiveConnectionOrThereIsRoomForOneMore(NavSession session)
at Microsoft.Dynamics.Nav.Runtime.NavLicenseValidator.ValidateLicenseForNewSession(NavSession session)
at Microsoft.Dynamics.Nav.Runtime.NavSession.Open(Boolean useUserPersonalization, Byte[] licenseToUse, Boolean allowAppsDisabledMode)
at Microsoft.Dynamics.Nav.Service.NSService.OpenConnection(ConnectionRequest connectionRequest)
at SyncInvokeOpenConnection(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.ErrorMappingCombinator(ServiceOperation innerOperation, NSServiceBase serviceInstance, String syncMethodName, Object[] inputs, Object[]& outputs)
at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.<>c__DisplayClass23_0.b__1(NSServiceBase serviceInstance, Object[] inputs, Object[]& outputs)
at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.PushPopCombinator(ServiceOperation innerOperation, NSServiceBase serviceInstance, String syncMethodName, Object[] inputs, Object[]& outputs)
at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.<>c__DisplayClass23_0.b__1(NSServiceBase serviceInstance, Object[] inputs, Object[]& outputs)
at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.CreateNewSessionCombinator(ServiceOperation innerOperation, NSServiceBase serviceInstance, Boolean requireNavUser, Object[] inputs, Object[]& outputs)
at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.<>c__DisplayClass23_0.b__1(NSServiceBase serviceInstance, Object[] inputs, Object[]& outputs)
at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.<>c__DisplayClass8_0.b__0()
at Microsoft.Dynamics.Nav.Runtime.NavPerformanceCounterSetter.UpdatePerformanceCountersWithAverageServiceOperationDuration(Stopwatch stopWatch, Action action)
at Microsoft.Dynamics.Nav.Runtime.NavPerformanceCounterSetter.UpdatePerformanceCountersWithAverageServiceOperationAction(Action action, NavSession session)
at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.PerformanceCounterCombinator(ServiceOperation innerOperation, NSServiceBase serviceInstance, String syncMethodName, Object[] inputs, Object[]& outputs)
at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.<>c__DisplayClass23_0.b__1(NSServiceBase serviceInstance, Object[] inputs, Object[]& outputs)
at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.InitClientTelemetryIdsCombinator(ServiceOperation innerOperation, NSServiceBase serviceInstance, String syncMethodName, Object[] inputs, Object[]& outputs)
at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.<>c__DisplayClass23_0.b__1(NSServiceBase serviceInstance, Object[] inputs, Object[]& outputs)
at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.TlsClearCombinator(ServiceOperation innerOperation, NSServiceBase serviceInstance, String syncMethodName, Object[] inputs, Object[]& outputs)
at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.<>c__DisplayClass23_0.b__1(NSServiceBase serviceInstance, Object[] inputs, Object[]& outputs)
at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
at System.ServiceModel.Dispatcher.MessageRpc.Wrapper.Resume(Boolean& alreadyResumedNoLock)
at System.ServiceModel.Dispatcher.ThreadBehavior.ResumeProcessing(IResumeMessageRpc resume)
at Microsoft.Dynamics.Nav.Runtime.NavSynchronizationContext.<>c__DisplayClass1_0.b__0(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()


ProcessId: 6572
Tag: 00000IA
ThreadId: 6
CounterInformation:

Eventviewer warning when the license limit has been reached.

Very useful information in my opinion, because if you filter on this type of message you could report to your application administrator to maybe buy more licenses for example. You don’t want complaining users right? This is a very good basis to ask for more licences if the limit is reached regularly.

To summarize: filter on Event ID 705 on the service tier machine to get all the Warning events. These events are related to Nav license limits which has been reached.

Maybe a useful tip: instead of reactive checking of the application log you could attach a task to this ‘event’. This task could be something like starting a program or sending an email for example.

How to – Filter ‘Case Insensitive’ in the Object Designer (Development Environment)

How to – Filter ‘Case Insensitive’ in the Object Designer (Development Environment)

We all know we can filter on objects in the Object Designer. You can for example search or filter on Type, ID, Name, Modified, Version etc. Now if for example I would to filter the Customer table my Filter could be: *cust*.

This however yields no results. The reason for this is that the database is enabled for Case Sensitivity. If I still would like to find the customer I need to make my filter Case Insensitive by prefixing it with the @ symbol. Like this:

However I don’t want to use a case insensitive filter every time :). For key users or admins  it could also lead too confusion why it is not working easier. There is a solution for this by disabling Case Sensitivity.

Tip: Before performing the steps below I recommend to create a FULL SQL backup to create a fallback scenario if problems will occur.

First double check if your database has been configured Case Sensitive. You can check this out for yourself by going to File > Database > Alter. Now go to the Collation tab and check if ‘Case -sensitive’ is enabled.

If you uncheck the option you will get a notification that this is not possible until you first enable ‘Validate Collation’:

Enable the checkbox Validate Collation first and press the OK button.

We can’t disable Case-sensitive yet because we must ensure now that you are the only user who is accessing the database. Therefore we need to enable the Single User option to perform the chosen database alterations. Go to Alter Database and enable Single User and press OK.

Tip: if you are getting an error that single user cannot be set, please ensure all servicetiers are stopped as well as they keep a SQL session maintained thus preventing setting the database in Single User mode.

If your database was set to Single User Mode, finally go to Alter Database and now you can disable the checkbox Case Sensitive. If the process has finished succesfully you will get this message:

Don’t forget to disable single user mode and start your servicetiers after! Uncheck Single user now:

In the end it should like this:

Double check if you can connect to your environment by starting the Windows client (RTC = Role Tailored Client) and good luck with Case insensitive filtering in the Object Designer!

When I started the client I received this message:

Textual: The tenant default in database NAV2017_CU17_CronusNL is not operational because the collation is incorrect. The tenant can be brought to the operational state by running the Sync-NavTenant cmdlet with the Mode parameter set to either Sync or ForceSync.

So the final step is to perform the synchronisation:

To summarize for the skilled users, perform the following steps to enable case insensitive filtering in the Object designer without using a case-insensitive filter:

  1. Enable Validate Collation
  2. Enable Single User mode
  3. Disable Case-sensitive
  4. Disable Single User mode
  5. Start service tier (Microsoft Dynamics NAV Service)

Perform Sync-NAVTenant (Powershell Cmdlet)

Error ‘The type NavDecimal is unknown’

During development I reveived this error ‘The type NavDecimal is unknown’:

The type NavDecimal is unknown

The error was triggered by renaming the primary key field. I tried to troubleshoot this by starting the debugger but this had no effect because my OnRename trigger didn’t had any logic. After some searching on my favorite forums Dynamics Community and Mibuso Forum I found similar errors but mine was different because I didn’t had any triggercode yet. After thorough investigation I found out that this problem was related to another old table which referred to my problemtable (Table Relation). After cleaning up the old unused table the problem was solved. It took me some time to figure this out so I thought it’s worth sharing this.

Dutch dates are displayed in English format

When working in Nav 2017 for example you could enter a date in a field of datatype Date. In my case the date was rendered in the English format:

How the date is displayed in the client is controlled by your regional settings in Windows:

If you change the format to Dutch, click Apply then the date is displayed in the format I prefer.

In order for the change to be effective you need to close Nav (all open Windows). Now the date is formatted according to the Dutch format:

xxxx

SystemService (Dynamics NAV Webservices)

In Microsoft Dynamics NAV the company name is part of the URL when you access published webservices. The ‘SystemService’ webservice allows you to retrieve the names of available companies. Even when you publish no webservices in Microsoft Dynamics NAV 2017 there is still this ‘builtin’ webservice that you can access. So let’s try it out! I took a look at the WSDL (Web Services Description Language). After looking at the WSDL I constructed a SOAP request like this:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sys="urn:microsoft-dynamics-schemas/nav/system/">
 <soapenv:Header/>
 <soapenv:Body>
 <sys:Companies/>
 </soapenv:Body>
</soapenv:Envelope>

I did sent this SOAP request to the NAV Service which is configured to allow SOAP Services. As a response I got a list of all the NAV companies:

<Soap:Envelope xmlns:Soap="http://schemas.xmlsoap.org/soap/envelope/">
 <Soap:Body>
 <Companies_Result xmlns="urn:microsoft-dynamics-schemas/nav/system/">
 <return_value>Company A</return_value>
 <return_value>Company B</return_value>
 <return_value>Company C</return_value>
 </Companies_Result>
 </Soap:Body>
</Soap:Envelope>

You could use these company names in your webservice URL to work with specific company data.

Could not register the Service Principal Name (SPN)

Recently I checked my SQL Server Error Logs. Quite some interesting information in my opinion, however I also found this message:

Date  25-7-2017 18:26:41
Log  SQL Server (Archive #3 – 25-7-2017 18:34:00)
Source  Server

Message
The SQL Server Network Interface library could not register the Service Principal Name (SPN) [ MSSQLSvc/SQL01.contoso.lan:NAV ] for the SQL Server service. Windows return code: 0x200b, state: 15. Failure to register a SPN might cause integrated authentication to use NTLM instead of Kerberos. This is an informational message. Further action is only required if Kerberos authentication is required by authentication policies and if the SPN has not been manually registered.

What’s this message about?
It cleary indicates thats SQL Server couldn’t register SPN’s. I’m running SQL Server under a ‘Virtual’ account so that should be the cause of the ‘error’.

From security perspective it is recommend to run SQL Server under the least privileged account: a virtual of MSA. For more information please go to Microsoft Docs.

In order to use Kerberos authentication with SQL Server there are some conditions to be met:

– The client and server computers should be in the same domain or trusted (2 way)  domains.
– SPN’s must be registered for SQL Server

In theory I can’t connect to my SQL Server using Kerberos authentication so why I’m still able to connect to my SQL Server? What kind of authentication is being used? Even other services from other machines are still able to connect (like Microsoft Dynamics NAV). In order to get an answer you could query SQL Server. With this query you’re able to view what kind of authentication scheme is being used:

select session_id,net_transport,client_net_address,auth_scheme from sys.dm_exec_connections

It turns out that Microsoft Dynamics NAV for example is falling back to Ntlm, intereseting… So let’s fix the SPN, restart SQL Server and look what’s happening? Now Microsoft Dynamics NAV 2017 is also connected to SQL Server but instead of Ntlm it is using Kerberos now.

In order to fix the SPN problem I manually registered the SPN in Active Directory (on the SQL Computeraccount). The errorlog states two SPN’s couldn’t be registered:

MSSQLSvc/SQL01.contoso.lan:NAV
MSSQLSvc/SQL01.contoso.lan:49753

For your information: I’m running SQL Server in a named instance called ‘NAV’ using Dynamic Ports. If you’re running SQL Server in the default instance on TCP Port 1433 the SPN’s are a little bit different. Please keep this in mind!