Wednesday, December 13, 2017

Find standard label translations

Microsoft aren't shipping the source standard label translations with the developer boxes. You only get the source for labels in en-us and the rest you only get as binary.

Here is what you can do if want to figure out how a particular label is translated.

First find the binary for the translated label file. This will be in the Resources folder under the package in question. For example, looking for the PRO labels from ApplicationSuite in Danish:

And next, open the dll in a tool allowing you to peek inside dll's. For example .NET Reflector.

Thursday, December 7, 2017

Misleading statements in 81215AE: X++ Programming and Advanced Topics in Microsoft Dynamics 365 for Finance and Operations, Enterprise edition

In Module 07 (and a few other places within same course) the importance of using the client / server modifiers and the RunOn property is discussed and emphasized.

However in D365 all X++ code is executed on the server. And thus the client / server keywords as well as the RunOn property are ignored.


I haven't tried the actual exam yet, so I don't know if this wrong assumption from the training material has sneaked into the exam as well. If there are questions on client/server settings, it probably has sneaked its way in since it's not of any importance anymore.

Wednesday, November 8, 2017

XQuery to save source code from all tables and classes

You can use this XQuery, with for example BaseX, to save all your source code from table and classes to an XML file:
  for $t in AxClass | AxTable  
  order by $t/local-name(.), $t/Name ascending

  for $y in ($t/SourceCode/Methods/Method)

  return <Code Type='{$t/local-name(.)}' Parent="{$t/Name/text()}" MethodName="{$y/Name/text()}" Source="{$y/Source/text()}"/>

Query range function: Less than date and not date null

There is a lessThanDate query function in AX, but it also selects blank dates.

Here is a suggestion for a similar function, that does not include the blank dates:
public static str lessThanDateAndNotNull(int relativeDays = 0)
    utcdatetime  currentDateTime;      

    currentDateTime = DateTimeUtil::applyTimeZoneOffset(DateTimeUtil::getSystemDateTime(), 

    return SysQuery::value(dateNull() + 1) + ' .. ' +            
           SysQuery::value(DateTimeUtil::date(DateTimeUtil::addDays(currentDateTime, relativeDays - 1)));  

Friday, November 3, 2017

XQuery to use with BaseX to find elements with no configuration key

Here is an XQuery that you can use with BaseX to find elements with no configuration key:
  for $t in AxTable | AxEnum | AxEdt | AxDataEntityView | AxMenuItemAction | AxMenuItemDisplay | AxMenuItemOutput
  order by $t/local-name(.), $t/Name ascending
  where fn:empty($t/ConfigurationKey)
  return <Element type='{$t/local-name(.)}' Name='{$t/Name/text()}' ConfigKey='{$t/ConfigurationKey}'/>

More on BaseX

Tuesday, September 26, 2017

Short book review: Implementing Microsoft Dynamics 365 for Finance and Operations, Enterprise Edition

Authors: Rahul Mohta (@RahulMohta8), Yogesh Kasat (@yogeshkasat) and JJ Yadav (@JJYadav)

Link to purchase:

This book covers the implementation process for a D365FOE project from A-Z. It combines theory with real life experience and it collects information you would have to look up multiple different places otherwise.

The book is very much up to date, also with information about the July 2017 release. It’s an impressive achievement to make the book so much up to date, taking into account the pace of changes from Microsoft. One thing that is not up to date though is the description of the database log implementation which has changed in the July 2017 update.

I currently work with ISV product development, not doing project implementations currently and I can say that I have learned a lot from this book. I could definitely see myself use this book as reference for future work.

A digital copy of the book was provided at no cost for me, by the authors, for the purpose of this short review.

Friday, September 22, 2017

The role of XLIFF files in the LCS Translation service

In the July 2017 release for LCS, support for XLIFF Translation Memory (TM) files was added. XLIFF (XML Localisation Interchange File Format) is an XML format used to standardize how translations are passed between different tools (Wikipedia).

Such a file holds a lot of information, like tags for source- and target languages, source- and target texts, indication whether the target text is the result of a machine translation, indication about if you actually want a translation of a given text (using {locked} in the comment of a label sets this flag to No), workflow status in relation to review of a translation and much more.

If you have existing translations and you need to add new translations to a project, you would want to tell the translation service about your existing translations to avoid getting them overwritten. You do that by requesting an XLIFF file as the first thing you do:

And here you upload a source and target label file:

In relation the tips 1,2 and 3, it seems like the label files are structured well enough for the tool not care about it. I have uploaded files with different number of labels, because new labels only have been added to source label file and I have used files where a few labels was not in the exactly same order. If it doesn't work out, you must prep the target file first.

As a result the browser returns the XLIFF file almost immediately.  Make sure your browser doesn't block downloads, otherwise nothing happens.

This is a small sample from a file:

You can also open it it Excel:

At this point you can actually start working with the translation. For example by inserting manual translations that you want included.

You can also use the "Multilingual app toolkit" from Microsoft to work with the file. The program is a bit outdated, latest supported Windows version is Windows 8.1 and the integration to Microsoft Translation services is broken. But as an editor the program works fine, and it has a fine UI for all the important tags of the XML file. 

It looks like this:

Now that you have the base for the translation, you can start the actual translation.

This takes you to the file upload dialog, where you upload zip files with your labels and with your XLIFF file:

When you click submit, the the job enters status processing.

There are some manual steps involved in the processing and you'll get an e-mail from the LCS team stating that this could take up to 5 business days. This manual involvement is related to the Microsoft Translator Hub being fed with your XLIFF files in order to train it using your existing translations. This should mean that it is able to pick up on how you have translated existing terms and reuse that way of translating for similar terms. For example (an example from AX 2012 that didn't go well there) the word "Visa" can be translated into two different words in Danish. Either as a required travel document (da: visum) or the credit card (da: Visa). When the translator hub knows what you have translated "Visa" into in other places in your label file, it has a better chance of determining what kind of visa you refer to.

In order to not start manual work just for the sake of this blog post, here is the result from another translation task.

The second file is a new label file which you can check into VSTS. You can do that directly or use this process if you might have other changes to the label file: Merge externally modified label files

The first file is a new XLIFF file including all the new translations. You can send this file out for manual review and the receivers can open it essential using a tool of their choice. Excel or the Multilingual App Toolkit would be good choices. You can actually also find a couple of online tools where you upload the file, edit the translations and download an updated file.

If the review causes changes to the XLIFF file, you can click the Regenerate button, upload the modified XLIFF file and almost immediately get a new label file based on that.

If you are 100% sure that only your source label file gets changes during development, you can keep this new XLIFF file and recycle it for your next translation. If both source and target could be changed, you should build a new XLIFF file.

Thursday, September 14, 2017

Sample loop through metadata of model

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Microsoft.Dynamics.AX.Metadata.Management;
using Microsoft.Dynamics.AX.Metadata.Modeling;
using Microsoft.Dynamics.AX.Metadata.Storage;
using Microsoft.Dynamics.AX.Metadata.Providers;
using Microsoft.Dynamics.AX.Metadata.MetaModel;

namespace MetaDataExample
    class Program
        static void Main(string[] args)
            string packagesLocalDirectory = @"J:\AosService\PackagesLocalDirectory";
            IMetadataProvider diskMetadataProvider = new MetadataProviderFactory().CreateDiskProvider(packagesLocalDirectory);

            var l = diskMetadataProvider.Tables.ListObjects("MyModelName");
            var le = l.GetEnumerator();

            while (le.MoveNext())
                AxTable t = diskMetadataProvider.Tables.Read(le.Current);



Wednesday, September 6, 2017

Important caveat with the "Chain of command" (CoC) feature

If you use CoC with the July 2017 application release, you need to compile and deploy the standard models you eventually use CoC with. The reason being that the standard models are compiled with Update 8 which didn't have CoC.

This is a temporary inconvenience, and will not be necessary after the "Autum" release.

So, if you write ISV/VAR solutions, you might want to postpone usage of CoC for anything you release before the "Autum" release.

Thursday, August 17, 2017

Package problem with LCS Code Upgrade to July 2017 release

If you get an error like "There is a problem with package 'ContactPerson'. Either the source version being upgraded from is incorrectly identified, or the target version has a package with the same name as a custom package." and you don't have a custom package of the same name, the solution could be the following.

In your existing source (Main branch) you should remove dependencies to the failing models from you model definitions. Check in the change and start the upgrade tool again.

When the upgrade tool is finished you should roll back your change in Main, to keep that branch working.

Wednesday, August 9, 2017

Database log changes in Update 8

Update 8 changes how the database log is logging changes to data. Before Update 8 this was handled through triggers in the kernel and then some application code.

In Update 8 this now happens on triggers created on the SQL Database for each table you enable logging on.

You can still find the old application code in Update 8, but it is not triggered anymore.

There is a bit more information on this community thread:

Friday, July 14, 2017

Clear the AOD cache, including the SysExtension cache, from the UI

There is really no place in the UI of "Microsoft Dynamics 365 for Finance and Operations, Enterprise Edition" where you can find a button to clear the AOD cache.

If you for example introduce a new class to an extension based on SysExtension this is a problem, because it wont be picked up until the cache has been cleared.

The earlier workaround doesn't seem to work in the "July 2017" update.

But the class to clear the cache is runable, so you can build a URL to call it:

https://[your AOS]

Or just make the URL for the menu item:
https://[your AOS]

Big thank you to Volker Deuss for giving me this idea.

Wednesday, July 12, 2017

New "Retail" model in "July 2017" creating backwards compatibility issues

The "July 2017" release has a new model called "Retail" and elements have been moved from other models to this model.

Even if you have made your own solutions exclusively with extensions, this might break your build because you might now need to add a reference to the "Retail" model.

But when you add that, you can't build your solution on the "1611" release anymore because build will complain about not knowing the "Retail" model listed in the Descriptor file.

So, even if your code works perfectly on both "1611" and "July 2017", you could have a need to branch out in VSTS to have two different Descriptor files.

Thursday, June 1, 2017

Merge externally modified label files

Sometimes you may need to have your label files reviewed or changed by an external party not having access to Visual Studio or your VSTS project.
This is a description of how a developer can merge the external changes back into the version control.

The tool used

You can of course use all sorts of different software to help you compare the files and merge the files. In this description we use the Diff and Merging tool that already comes with Visual Studio. This is the tool you'll see open when you have conflicts between local files and files in the source control repository.

These are the steps

The Diff and Merging tools doesn't have a menu in Visual Studio for opening it. So it must be opened through a command prompt and it must be given parameters about the files you want to work with.

Open Visual Studio

Open Visual Studio as you'd normally do. Remember to open it with "Run as administrator".
Make sure that Visual Studio doesn't have a label dialog open.

Get latest label files

Ensure that your system is updated with the latest label files from the version control.

Open the command prompt

1. Click the Window button:

2. Click the arrow:

3. Scroll to the right until you find the "Developer Command Prompt for VS2015":

4. Right-click it and choose "Run as administrator":

5. This opens the command prompt:

Start the merge tool

The merge tool needs to know of four file names:
  • Source file (in our case the current label file)
  • Target file (in our case this is the external file you have to merge in)
  • Base file (in our case also the current label file)
  • Result file (in our case also the current label file – as this is where we want to store the merge)
The following is an example with labels in a package called "EGDiagnosticsPlatform" and a model called "EG Diagnostics Platform". The external label file has been placed in H:\External.

Here are my changes, shown with another compare tool (Code Compare):

The command prompt looks like this:
vsdiffmerge "J:\AosService\PackagesLocalDirectory\EGDiagnosticsPlatform\EG Diagnostics Platform\AxLabelFile\LabelResources\en-US\EGDiagnosticsPlatform.en-US.label.txt" "H:\External\EGDiagnosticsPlatform.en-US.label.txt" "J:\AosService\PackagesLocalDirectory\EGDiagnosticsPlatform\EG Diagnostics Platform\AxLabelFile\LabelResources\en-US\EGDiagnosticsPlatform.en-US.label.txt" "J:\AosService\PackagesLocalDirectory\EGDiagnosticsPlatform\EG Diagnostics Platform\AxLabelFile\LabelResources\en-US\EGDiagnosticsPlatform.en-US.label.txt" /m

Here it is in the command prompt:

And this is the result:

Note that this way of looking at source vs. target, makes the tool suggest to remove the new labels made in-house while the file has been out for review. This is something you must fix manually.

Not what we want:


Version control

Note how running the tool immediately flagged the label file as a pending change (because we choose it to be the Result file):


If you don't want to have to figure out how to fill the prompt each time do this merge, you could use a PowerShell script like this:

Run PowerShell as Administrator

Go to the location of the script and run it

Enter the location of your internal file and of the external file:

Version with parameters

If you need to merge the same filter repeatedly, you might want another version of the script. If I knew PowerShell better, I'm sure these could be combined, so the script only asks for parameters if they are not given.

The base function

The call of the function

Running it

Saturday, May 27, 2017

First book about Dynamics 365 for Operations development is out

From the publishers homepage:

"Dynamics 365 for Operations is the ERP element of Microsoft’s new Dynamics 365 Enterprise Edition. Operations delivers the infrastructure to allow businesses to achieve growth and make better decisions using scalable and contemporary ERP system tools.

This book provides a collection of “recipes” to instruct you on how to create—and extend—a real-world solution using Operations. All key aspects of the new release are covered, and insights into the development language, structure, and tools are discussed in detail.

New concepts and patterns that are pivotal to elegant solution designs are introduced and explained, and readers will learn how to extend various aspects of the system to enhance both the usability and capabilities of Operations. Together, this gives the reader important context regarding the new concepts and the confidence to reuse in their own solution designs.

This “cookbook” provides the ingredients and methods needed to maximize the efficiency of your business management using the latest in ERP software—Dynamics 365 for Operations."

Buy it from the publisher or from Amazon.

Friday, May 19, 2017

Use tags to find related bits and pieces in your code base

A lot of elements, if not all, in Dynamics 365 for Operations (D365FO) has a property called "Tags".

With this property you can link all sorts of different otherwise unrelated elements. You could for example use this as part of a bigger change you need to do to your code base, marking all the bits you need to modify.

Adding a tag is as simple as just using it:

For Visual Studio to find places where the tag is used, you need to do a  build with the "Build cross reference data" option checked:

And here is where you search for tags:

And here is the result:

This ought to work for code to. The editor knows about the tags and has intellisense for them:

But the "Find tag references" tool doesn't pick them up. I wonder if that is a bug or not.

And in my opinion you should try to not go overboard tagging away all day long.

Monday, May 15, 2017

FormRun.wait, Box and ChangeCompany - a poor cocktail

I have had some code like this (simplified for the purpose of the example):
    formRun = new FormRun(...);

If you run this code and manually change company while the form is open and "waiting", the call to Box will make the system freeze up. I have reported this as a bug, but it is not accepted to be fixed.

The workaround, or you could argue proper solution, is to add an event handler for formRun.lifecycleHelper().StageChanging and run the Box code when the stage of the form changes to "Closing". That way Box is called before the form is entirely closed and the company account is changed, and then Box runs all right.

Friday, April 7, 2017

Use Microsoft Flow to start up your Azure VMs

Having Azure VM's running when no one uses them is the cloud equivalent of setting your money on fire.

With the ARM deployments we can do for D365fO now, we can pretty easily make the machines shut down automatically based on a schedule:

But how about startup? If you start a machine manually it takes a while before you can connect to it and use it. So it is preferred to start machines before the workday starts. 

If you control startup with scheduled RunBook scripts you risk starting machines that will not be used during the day. Developers might be on other projects, being sick or being on vacation.

So I have been looking into using Microsoft Flow to start machines. The idea is that a developer opens his/her Flow app before leaving their home in the morning, to start the machines they want to work on that day. Here is how that could look in the Flow app:

To get there, first step is to create an Azure Automation account and create the RunBook for starting a VM. You can find the RunBook as a template in the Azure Portal. The process is very well described in this article on the Axology blog:

The Flow app is very simple to setup. Here are the steps for creating the app button (sorry, some of this is in danish).

First add the manual trigger:

Then add the action, which in this case is an "Azure Automation - Create job" action:

Finally I get a notification when the job is done. Not when the machine actually runs, but when the job kicking off the startup is done:

That is it for a really simple flow. You can probably think of a lot of bells and whistles to add.

I would like to try it out with one of the physical buttons that works with Flow, like Flic, as the trigger:

A button is ordered...

Language issue in AX 2012 with Views built on security tables

Some of the security related system/kernel tables in AX 2012, like for example SecurityRole, is backed by Views in the model store.

If you look at the Views in the model store you can see that some fields hold a label id rather than a text. For SecurityRole, the fields Name and Description holds label ids.

Somewhere in the AX kernel these label ids are converted to actual texts according to the language of the user. So inside AX we don't see these labels, but we see the language specific texts.

This is also the case if you create a View where these tables are part of the meta data.

However if you change the language for your user, it doesn't seem like these Views are updated according to the new language. They keep returning data in the previous language, even after restarting the client and AOS. The only way I have found to make it use the new language is to manually synchronize the view from the AOT.

Thursday, April 6, 2017

Resolve dll references for a project generated from a template

When you create a new project from a template, for example a new Best Practice Rules project, you might get a bunch of references that aren't resolved:

To resolve these you can individually point each reference to the correct dll, or you can take the following faster approach.

In Solution Explorer, right-click your project node and click Properties. The Project Designer appears:

Select the Reference Paths page. In the Folder field, type the path of the folder that contains the items you want to reference, and then click the Add Folder button:

The path for most D365fO dll's is J:\AosService\PackagesLocalDirectory\Bin\

Click Save to save the setting and then close the dialog:

And ... voilĂ :