Dynamics 365 Business Central

Hey everyone!

I’m off enjoying the March Break with my family this week but I wanted to get this out, since it’s (finally!) been announced by Microsoft that the product formerly known as Dynamics ‘Tenerife’ will be made available April 2, 2018 under the name Dynamics 365 Business Central.

As the announcement states, it’s going to be available April 2, 2018 to 14 countries: United States, Canada, United Kingdom, Denmark, Netherlands, Germany, Spain, Italy, France, Austria, Switzerland, Belgium, Sweden, and Finland. Australia and New Zealand will be available on July 1, 2018. Take note that you must purchase Dynamics 365 Business Central through a Cloud Solution Provider (CSP) partner.

I don’t have much else to say right now, other than I’ve been working with Dynamics 365 Business Central for a while now and I think everyone’s going to love it! This product is moving fast and the advancements being made are amazing! Definitely some very exciting times ahead!

If you want to read more, check out the Dynamics 365 Business Central website here.

Until next time….happy coding!


AL Extensions: Translate your solution using Microsoft Dynamics Lifecycle Services

Hi everyone!

Today’s post is about language translations. I’ve not really done much with language translations in the past, but it always seemed as though it was a very tedious thing to have to do.

This post though is going to show you how to do it quite quickly, and if all goes well you can translate your AL extension in a matter of minutes.


Note that in order to perform the tasks in this post, you will need access to Microsoft Dynamics Lifecycle Services (LCS). If you do not have access contact your system administrator, or the person that manages your CustomerSource/PartnerSource account, as the systems are linked in some way.

Let’s Get Started

Assuming you have already developed your AL extension, you need to enable the new translation feature. You can do that by adding the following line to your app.json:

"features": ["TranslationFile"]

This feature will cause a new translation file to be generated when the extension is built. The translation files are created using the standard XLIFF format that is used to pass data between system for the purposes of language translation. For more info on XLIFF, check here. You will find the translation file at the root of your AL project in a Translations folder.

You’re also going to need to change all of your ML properties as they are being deprecated (as of this post though they are still available). You can read more about that here.

Ok, you have now enabled the new translation file feature, and you’ve updated all of your ML properties, you need to build your extension. Once that completes, look for the newly created XLF file in the Translations folder. This is the file that we need to submit to the translation service.

The Translation Service

Before we get into submitting the file, note that in my solution my base language is English (US). I’ll be translating that to Canadian French. Substitute the appropriate languages for your solution.

Here are the steps to perform the translation:


  • Select the ‘+’ button at the top left to make a new request and fill in the request based on your desired translation. Make sure to select Microsoft Dynamics NAV as the product and the appropriate product version.


  • Once you have filled in your request, press Create to submit the request. At this point you just wait. You should receive an email from LCS stating that “A new request has been created.”
  • After a short period of time (for me this was only about 2 minutes!!) you will receive another email from LCS stating “The request has been completed.”
  • Follow the link in the email and you will be brought to a page that shows you the details of your translation request.
  • Click Request output at the left side of the screen.
  • Click the DownloadOutputLink link to download your translated XLF file. and extract it to the Translations folder in your AL project. It will have a new file name so it should not overwrite your existing file. Do not remove the original XLF file as that still represents the base language of your extension!

That’s it!

Now all you have left to do is to rebuild your extension with the new translation file and voila…..you now have a multi-language extension! Test it out by changing to the appropriate language in the web client.

Ongoing Maintenance

Once you have non-base translation files in your AL project, they do not get updated when the extension is built. For example, if you add a new field with a caption and build your extension, the base language XLF will get updated to include the new field. Your non-base XLF files will not, so you will need to revisit LCS and submit a new base language file to get those updated.

Hopefully this service has works as well for you as it seems to for me. I was actually quite shocked at how fast I was able to get the translated file back.

That’s all for now, happy coding!

AL Extensions: Accessing the Device Camera

If you’ve been doing any V2 extension development, you like are aware that we cannot use any .Net interop in our code.

While on premise V2 development will eventually gain access to .Net variable types, if you’re coding your extension to run in AppSource, you will remain locked away from using .Net interop in your code because the risk of these external components is too large for shared cloud servers.

Unfortunately this means that we lost the ability to interact with the device camera, as it was accessed using .Net.

In C/AL, the code to take a picture with the device camera looked like this:

   IF NOT CameraAvailable THEN
   CameraOptions := CameraOptions.CameraOptions;
   CameraOptions.Quality := 50;

It’s simple enough code, but the problem in the above example is that both CameraProvider and CameraOptions are .Net variables, and therefore cannot be used in V2 extension development.

I’m happy to say though that this problem has been resolved. Yes, the underlying architecture still uses .Net controls, but Microsoft has introduced a new Camera Interaction page which acts basically like an api layer. Through this api layer you can interact with the .Net camera components just as you did in C/AL.

Not a huge change to wrap your head around at all. In your extension you will code against the Camera Interaction page instead of against the .Net controls directly. Inside the page are all the original camera functions that you were used to using before.

This greatly simplifies our extension code and allows us now to use the camera from our extensions.

The code to take a picture would now look like this:

local procedure TakePicture();
        CameraInteraction: Page "Camera Interaction";
        PictureStream: InStream;
        if(CameraInteraction.GetPicture(PictureStream)) then begin
            Picture.ImportStream(PictureStream, CameraInteraction.GetPictureName());

That’s it! Now you can use the device camera from your V2 extensions.

Happy coding!

Enable Personalization in the Dynamics NAV 2018 Web Client

The recent release of Microsoft Dynamics NAV 2018 has brought a lot of improvements to the Web Client, one of those being the ability for users to (finally!) do personalization directly in the client. No longer do they need to jump over to the Windows Client for that!

If you have installed NAV 2018 though, you might be wondering how you do the personalization. Well….it’s not enabled by default.

To enable it, you need to modify the Web Client configuration, which is done within the new navsettings.json file. Yes, out with the old web.config and in with the new json-based file! Read more about this here.

You have 2 options for changing the configuration:

Edit Configuration File Directly

To edit the Web Client configuration directly, open the navsettings.json file and add the following line:

"PersonalizationEnabled": "True"

The default location for the json file is here:

After you have changed the file, save it, and then restart the Web Client website via IIS, or by executing iisreset at the command prompt.

Using PowerShell

As I’m a huge fan of PowerShell, this is my preferred method of doing pretty much anything. Using the Dynamics NAV 2018 Development Shell (in admin mode of course), you can use the Set-NAVWebServerInstanceConfiguration commandlet to update Web Client configuration.

To enable personalization, you would run the commandlet like this:

Set-NAVWebServerInstanceConfiguration `
     -Server [MyComputer] `
     -ServerInstance [NAVServerInstanceName] `
     -WebServerInstance [MyNavWebServerInstance] `
     -KeyName PersonalizationEnabled `
     -KeyValue True

For more details on the full commandlet syntax, look here.

Performing Personalization

Once you do one of the above steps, you’ll be able to log into the Web Client and select the Personalize action, which is found at the top of the Web Client under the settings cog:


That’s all there is to it.

Happy coding!

AL Extensions: Importing and Exporting Media Sets

One of the things that has changed when you are building V2 extensions for a cloud environment is that you cannot access most functions that work with physical files.

This presents a bit of a challenge when it comes to working with the media and media set field types, as the typical approach is to have an import and export function so that a user can get pictures in and out of the field.

An example of this is the Customer Picture fact box that’s on the Customer Card:


As you can see, the import and export functions in C/Side leverage the FileManagement codeunit in order to transfer the picture image to and from a physical picture file. These functions are now blocked.

So…..we have got to take another approach. Enter streams.

Using the in and out stream types we can recreate the import and export functions without using any of the file based functions.

An import function would look like the following. In this example, the Picture field is defined as a Media Set field.

local procedure ImportPicture();
   PicInStream: InStream;
   FromFileName: Text;
   OverrideImageQst: Label 'The existing picture will be replaced. Do you want to continue?', Locked = false, MaxLength = 250;
   if Picture.Count > 0 then
     if not Confirm(OverrideImageQst) then

  if UploadIntoStream('Import', '', 'All Files (*.*)|*.*', FromFileName, PicInStream) then begin
    Picture.ImportStream(PicInStream, FromFileName);

The UploadIntoStream function will prompt the user to choose a local picture file, and from there we upload that into an instream. At no point do we ever put the physical file on the server. Also note that the above example will always override any existing picture. You do not have to do this as media sets allow for multiple pictures. I’m just recreating the original example taken from the Customer Picture page.

For the export we have to write a bit more code. When using a Media Set field, we do not have access to any system function that allows us to export to a stream. To deal with this all we need to do is loop through the media set and get each of the corresponding media records. Once we have that then we can export each of those to a stream.

That would look like this:

local procedure ExportPicture();
   PicInStream: InStream;
   Index: Integer;
   TenantMedia: Record "Tenant Media";
   FileName: Text;
   if Picture.Count = 0 then

   for Index := 1 to Picture.Count do begin
      if TenantMedia.Get(Picture.Item(Index)) then begin
         if TenantMedia.Content.HasValue then begin
            FileName := TableCaption + '_Image' + format(Index) + GetTenantMediaFileExtension(TenantMedia);
            DownloadFromStream(PicInstream, '', '', '', FileName);

We use the DownloadFromStream function to prompt the user to save each of the pictures in the media set. As in our first example, there are no physical files ever created on the server, so we’re cloud friendly!

You may notice that I use the function GetTenantMediaFileExtension in the export example to populate the extension of the picture file. Since the user can upload a variety of picture file types, we need to make sure we create the file using the correct format.

The function to do this is quite simple, however there is no current function in the product to handle it, so you’ll have to build this yourself for now. Hopefully in the near future this function will be added by Microsoft.

local procedure GetTenantMediaFileExtension(var TenantMedia: Record "Tenant Media"): Text;
   case TenantMedia."Mime Type" of
      'image/jpeg' : exit('.jpg');
      'image/png' : exit('.png');
      'image/bmp' : exit('.bmp');
      'image/gif' : exit('.gif');
      'image/tiff' : exit('.tiff');
      'image/wmf' : exit('.wmf');

Until next time, happy coding!


Dynamics NAV 2018 Available Now

Microsoft Dynamics NAV 2018 is now available for download!! You can download it here, or visit the Get Ready For Dynamics NAV site for more information.

Other resources of interest:

Happy coding!


AL Extensions: Extending an Extension

Something I’ve been meaning to write about since I started developing extensions is how to extend another extension, or in other words, the process of creating a dependent extension.

For the sake of keeping things straight in this post, I am going to refer to the following 2 extensions:

  1. Parent: the extension that is being depended on.
  2. Child: is dependent on the Parent extension.

So, without further ado, here we go!

First, develop and build the Parent extension. Take note of the following values from the app.json of the Parent extension:


Now publish the Parent extension to your development system so that we can download the symbols for the Child extension.

Time to move to developing the Child extension, where we need to specify the dependency to the Parent extension. We do that using the following property in the app.json file.


Using the id, name, publisher, and version values from the Parent extension, we populate the property as follows:


As soon as you save the app.json file, you will be prompted that symbols are missing. This is because the AL compiler is now looking for the symbols for the dependent extensions.

Click the Download Symbols button in the VS Code notification and download the symbols form the development database where you published the Parent extension.

Take note that the dependencies property accepts an array of values, which means you can specify multiple dependency extensions.

Once the symbol download is complete, you will be able to reference any objects, events, functions, etc. that are available in the Parent extension. You’ll also be able to extend the Parent extension as needed.

Be Aware

  • Make sure that when you publish your extensions, you must do the extension that are depended on first (e.g. Parent). If you try and publish the extension with the dependency first (e.g. Child), it will error stating that references do not exist in the database.
  • When you remove extensions, you must remove the extensions that have the dependencies first (e.g. Child) as you cannot remove an extension that has other extensions depending on it.
  • If you update any of the extensions that are being depended on in your development database, you must also change the corresponding version in the dependencies property of any extension that is dependent on it. Once this is done you will be prompted to download the new symbols file. If you don’t do this you will be developing off of an old version of the symbols ad publishing the extension may fail.

How is this useful?

  • A Dynamics NAV ISV can use this method to create a “library” extension that contains standard functionality that is required to be available across one or more functional extensions.
    • By the way, this scenario is fully supported for any extensions submitted to AppSource. The library extension does not appear in AppSource. When a customer installs the functional extension, the library extension will also get installed.
  • A Dynamics NAV partner could create an extension that contains some common functionality they deliver to all of their customers. They could then create a dependent extension that contains a customized layer on top of the original extension that is unique to each customer.
  • A Dynamics NAV partner needs to extend another partner’s extension.
    • If you are going to do this, you must have access to getting the symbols for the extension you are building on top of. You don’t need the actual .al source files, just the symbols file.
  • A customer who develops their own custom solution can build their own extension and make it dependent on another extension that’s in their system.

Until next time, happy coding!