Modified Base App on Docker

How to get started with modifying the Base Application using Docker

Many partners are still focused on doing custom development for their customers with their one-off implementations. MANY of those customers are existing customers with existing NAV systems with existing customized objects. As much as everyone wants to go to extensions only, and most partners see the need and are more than willing to make the necessary changes, the reality is that many of these existing customers do not want to pay for migrating all of their custom modifications. This reality comes with the need to modify the base app. Since C/SIDE is no longer available, the only way to do this is to use VSCode. This post will explain how you can create a Docker container, and use that container to do modifications on the Base Application.

To get started, click here to read the article on docs.microsoft.com. I say ‘get started’ because it was not enough to get me all the way there, which is the reason why I wrote this post. This article seems to have been written for an actual installation from the product DVD, and there were some additional things you need to know to make it all work if you want to use Docker. At least, that is per the date of this post, because things may change :). I’ll try to revisit this post if it does change.

Alright, so to make this work, you need a few things:

  • A Docker container that is based on the latest Business Central Docker image.
  • Configure the Service Tier in the container
  • Extract the objects from the container into a new AL workspace
  • Uninstall and Unpublish the Base Application and its dependencies

Create a new Container

For Business Central development I always use the NavContainerHelper module, so before you use any of the commands in this post, update your module:

Update-Module navcontainerhelper

To get the latest Docker image for Business Central I will be using the ‘mcr.microsoft.com/businesscentral/onprem:na-ltsc2019’ image. You can leave the ‘ltsc2019’ part out if you are not sure about the host OS or if you are on Windows Server 2016. You can substitute ‘na’ for your own localization, or leave that tag out altogether if you want to be on the W1 version. To read about which image to use, visit Freddy’s blog here and follow the links to what you need to know. Here is the script that I used to create my container:

$imageName = 'mcr.microsoft.com/businesscentral/onprem:na-ltsc2019'
$licenseFile = '<path to your BC 15 developer license>.flf'
$ContainerName = 'mysandbox'
$UserName = 'admin'
$Password = ConvertTo-SecureString 'Navision4ever!' -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential ($UserName, $Password)


New-NavContainer `
    -accept_eula `
    -containerName $ContainerName `
    -imageName $imageName `
    -licenseFile $licenseFile `
    -auth NavUserPassword `
    -alwaysPull `
    -Credential $Credential `
    -includeAL `
    -updateHosts `
    -additionalParameters @("-e customNavSettings=ExtensionAllowedTargetLevel=OnPrem")

I use the ‘-alwaysPull’ switch to make sure that I always have the latest version of the Docker image. The ‘-includeAL’ switch is necessary to include references to the DotNet assemblies in the Docker container. The ‘-additionalParameters’ switch (h/t @tobiasfenster) is used to set the ExtensionAllowedTargetLevel property to ‘OnPrem’. I’ll explain how to set this with a simple PowerShell Cmdlet in a minute.

One more important switch is the ‘-useCleanDatabase’ switch, which can be used to uninstall and unpublish the Base Application and its dependencies, as I will discuss in a little bit. At this point, you have a vanilla Docker container with the latest on premises version of Business Central.

Configure the Service Tier

As the Doc states, there are three things you need to set. It is not very clear exactly how to do that, and not at all how that works on Docker, so let me just explain from scratch.

First, you need to know how to look at, and modify, the Service Tier settings inside the container. Some of these types of commands are available in the navcontainerhelper module, but some of them are not. I did find a Cmdlet to see the settings, but I could not find one to actually modify them. So, to cover all of it, I will show you how you can connect to the container and run regular BC PowerShell Cmdlets from inside the container.

Open a PowerShell ISE window as administrator, and run the commands in the screenshot

Our container name is ‘mysandbox’, and you connect to it by using the ‘Enter-BCContainer’ Cmdlet. You can see how the prompt changes to show you that you are inside the container. At this stage, the navcontainerhelper does not work, so you will have to use the regular BC PowerShell Cmdlets. The next Cmdlet shows you all the properties of the Service Tier that runs inside your container, which in this version of Business Central is called ‘BC’.

According to the Doc, the following settings are important. I am using the names that are used in PowerShell rather than the names in the Doc.

  • ExtensionAllowedTargetLevel should be set to ‘OnPrem’, although it seems that the value ‘Internal’ also works.
  • DeveloperServicesEnabled should be set to true. This should be the default value of this particular setting
  • There is also a mention of the EnableSymbolLoadingAtServerStartup property in the Doc, but I’ve received confirmation (h/t @freddydk) that this property was meant for hybrid C/AL and AL environments, so that is not needed anymore for BC 2019 wave 2

To modify these settings, use the following PowerShell command

Set-NAVServerConfiguration `
      -ServerInstance BC `
      -KeyName ExtensionAllowedTargetLevel `
      -KeyValue OnPrem

After modifying those settings, restart the service tier using the ‘Restart-NAVServerInstance -ServerInstance BC’ command. At that point, the service tier in your container should be configured for doing on premises development. The next thing you need to do is get the application objects out of the container.

Create AL Workspace from Base App

This step is easy, using a navcontainerhelper Cmdlet, so you need to first exit the container (type ‘exit’ and then enter). Then, run this Cmdlet:

$ContainerName = 'mysandbox'
$UserName = 'admin'
$Password = ConvertTo-SecureString 'Navision4ever!' -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential ($UserName, $Password)

Create-AlProjectFolderFromBcContainer `
    -containerName $ContainerName `
    -alProjectFolder 'C:\MyProjects\BaseApp' `
    -useBaseAppProperties `
    -credential $Credential 

One thing to note here is that the ‘-useBaseAppProperties’ switch uses the properties from the container. You will end up with a fully functioning AL workspace, with an app.json and launch.json that is configured to look inside the container for the objects and the DotNet probing path. You will need to configure this yourself if your configuration needs to be different. But, since we’re making this work for a standard container, we’re going to use the standard configuration as well.

One other important thing to note…. As I am writing this post, I’ve had a persistent error message that prevented me from compiling the app, which I narrowed down to having to remove the translation files. The annoying part is that the error message itself does not mention the translation files, but it started working again after I removed them. In your new BaseApp folder, there is a folder called ‘Translations’. Remove all files from that folder, except the ‘*.g.xlf’ file.

Update 2019/11/27 follow up on the translation file issue

One final thing to note is that this is just a simple AL workspace. In a real life situation, you are doing this for a particular customer, so you need to think about source control, workspace settings, things like that. There are some capabilities in the Cmdlet, so take a look here to see all the available parameters of the Cmdlet.

The last thing you will need is to download the symbols for the system apps from the container. The Doc also mentions adding the assemblyProbingPaths to the workspace settings, but if you used the ‘-useBaseAppProperties’ switch, that is already taken care of for you and the setting will point to one of the container’s shared folders.

Uninstall / Unpublish Base App

In the previous step, you’ve created an AL workspace with all of the objects from the Base Application. Now, your container already has a Base App, so in order to create a modified Base App, you will have to get rid of the standard one first. You can be a PowerShell warrior and run the Cmdlets in this section, or you can also use the ‘-useCleanDatabase’ switch in the New-BCContainer Cmdlet in the first section. This will remove the Base App and all its dependencies from your container right away.

On to the PowerShell… In the Doc, under bullet 11, you will find the functions to accomplish this. These are regular NAV PowerShell Cmdlets, so you will need to enter the container first:

function UnpublishAppAndDependencies($ServerInstance, $ApplicationName)
{
     Get-NAVAppInfo -ServerInstance $ServerInstance | Where-Object { 
    # If the dependencies of this extension include the application that we want to unpublish, it means we have to unpublish this application first.
    (Get-NavAppInfo -ServerInstance $ServerInstance -Name $_.Name).Dependencies | Where-Object {$_.Name -eq $ApplicationName}
 } | ForEach-Object {
    UnpublishAppAndDependencies $ServerInstance $_.Name
 }

 Unpublish-NavApp -ServerInstance $ServerInstance -Name $ApplicationName
}

function UninstallAndUnpublish($ServerInstance, $ApplicationName)
{
    Uninstall-NavApp -ServerInstance $ServerInstance -Name $ApplicationName -Force
    UnpublishAppAndDependencies $ServerInstance  $ApplicationName

}

This loads the functions into memory, and then you can run the script:

UninstallAndUnpublish -ServerInstance BC -ApplicationName "Base Application"

This will completely remove the Base App and its dependencies.

Ready to Start Developing

That’s it, you should now be ready to start your development. See how that works. Add a field to a table, add that field to its Card page and hit Ctrl+F5. It will probably take a while to compile, but you should see your new field on the page.

Now I do need to say that I completely and wholeheartedly agree with the entire community, and code customizations should really not be done anymore. All development should be done using extensions instead of change the Base App itself. It makes everyone’s life a lot easier if you minimize the amount of development done to the Base App, so even if you have no other choice, try to design the development in such a way that most of it is in an extension, and only modify the Base App for the parts that you can’t figure out how to do in an extension.

Update 2019/11/27: created a GitHub repo with the scripts

A Very Crappy 2019

2019 has been a very difficult year for me on a personal level, in fact the most difficult I can remember. I just got back last week from spending 5 weeks in Holland, and I finally feel like I can put some of my thoughts into words and share what I’ve been through this past year. I’ve been almost invisible on this blog because I’ve had other, more important, things on my mind. Whether I can find back my enjoyment of writing about things or not will determine if I will start writing again. Right now I feel very empty, and I have no desire to write at all.

I am at heart a very private person and don’t really want to show my inner most thoughts (ha! funny if you look at how long this post is). On the other hand, I feel like I want to write about it, because it might help to deal with it that way. I’m sorry if I ramble on, I just wanted to get this off my chest.

A Good Start is Half the Work

The year 2019 started with three big ones. First, I’m going through some medical stuff related to my lungs, and January 3 was the first of MANY tests and visits to a long list of doctors throughout the year. Initially it looked like it could be very serious, but fortunately I have no life threatening condition, and I’m expected to recover completely (well for the most part).

Second, we were trying to deal with a personal family matter that involves one of the most important people in my life. I am so SO happy to say that this situation has been resolved for the most part, but during the first half of the year it was not certain that this would be possible. Extremely personal, extremely troubling.

Lastly, my work situation was going through a big change. Back in 2017 I had made a significant investment to buy myself into a partnership with a lot of promise, and by the end of 2018 the situation had completely imploded. I still do not understand how badly I could have misjudged this situation (well one person really).

These three things alone were completely dominating my every thought. I was walking around with a big knot in the pit of my stomach. If that wasn’t enough, I was about to get some really disturbing news…

Meanwhile, in Holland

About 10 years prior my mom had beaten kidney cancer, and in Holland that means you get screened every year for 10 years. This year was her last screening, and in January they discovered a mass in her lungs: it was lung cancer, it was malignant. Over the next few months she’d go through chemo and radiation, and she was expected to completely recover from this without a problem, they got it early so the tumor was only the size of a peanut. In April I went to Holland for a couple of weeks to be there for moral support. When I was there, I noticed that my dad was having some trouble breathing.

After I got back to the US, another mass was found in her lung, which they were going to surgically remove at the end of May. Meanwhile, my dad was having more and more trouble breathing, and experiencing intense pain in his chest and back. As my mom was recovering from her surgery (she was literally in the recovery room at the hospital), my dad went into the same hospital, to the same lung doctor as my mom, for his breathing problems and to get tested, scanned, and prodded. On June 11 we received his diagnosis: stage 4 lung cancer, it has spread to other organs and his spine, no recovery possible, outlook not very good although no doctor was willing to give an actual time frame. As my mom was declared ‘clean’ (scheduled for a follow up mid September), my dad was basically given a death sentence.

The only thing they could really do was try to slow down the progress and keep him ‘comfortable’. Now if you have any experience with cancer, you know what a fucking crock of shit that is. There is nothing ‘comfortable’ about this. Nobody gave us a concrete prognosis, so there was no way to tell how much time we really had with him. It was clear though that this was it, my dad would not grow old…

Unexpected Trip

My wife is a nurse, and she immediately got very business-like. She did not want to alarm me, but she basically insisted that we book a couple of tickets to Holland right away to spend some quality time with my dad, in person, while he was still capable. The general prognosis for stage 4 lung cancer is just a couple of months, despite the hopeful message that the doctors like to give people. The statistics of 6 months to a year are really the exception, most lung cancer patients at that stage don’t make it past 3-4 months.

We traveled to Holland in early August and stayed with my parents. The two of us did some touristy stuff, but neither one of my parents were up to do anything with us. My dad’s pain was so severe that he could really only sit up for meals, and the rest of the time he had to lay down to relieve his pain. My mom was doing pretty well, considering, but she was not strong enough to go out and do much more than just some grocery shopping. It was heartbreaking, and I can’t describe how difficult it was to live through it, but we said our goodbyes to my dad and traveled back home knowing that we would never see him alive again.

More Bad News from Holland

As August was drawing to a close, my dad called on a Wednesday night. He’d been taken to the hospital because his pain was just unbearable. They took more images and discovered that his body was just riddled with cancer, most urgently his liver. At this point it was a matter of days until the cancer would take him, and he was done fighting.

My dad had decided to move to a hospice and opt for something called ‘palliative sedation’, where they give you a sedative that is strong enough to go to sleep, and they discontinue food and liquids. The result is that you die in your sleep, usually within 2-3 days. This sounds really bad, and especially for people from countries where this is taboo quite concerning. If you want to say something, please send me a private message. I’d be happy to tell you all about it. Euthanasia is legal in Holland, but the process is very strictly regulated and actually quite difficult to get through it. Palliative sedation is something that is not quite euthanasia, but still a way to have control over your own end of life planning. To put it bluntly, euthanasia takes about 2 weeks from when you start the process to the moment of death, and my dad didn’t have that much time.

Anyway, he had made arrangements to go to sleep the following Monday. All of a sudden, there was a date, it was no longer theoretical….. Just a couple of weeks after I had seen him in person, he had gone from being able to walk around the house to being in so much pain that staying alive was too painful for him.

Another Unexpected Trip

I was planning to stay in the US at the end. I had talked about this with my wife, my parents and my siblings. After all, we had said our goodbyes, and I was at peace with that. Now that there was a date though, I could not stay away. It cost a fortune (PURE greed by the airlines, taking advantage of people’s need to travel at a short notice), but I booked the next flight to Amsterdam.

By the time I arrived in Holland, my dad was at the hospice, and they had switched him to ‘the good drugs’. His pain was bearable (which they had not been able to do at the hospital), so much so that he changed his mind about starting the sedation on Monday. He was able to stay with us for another few days, and spend some time with his family and friends. He declined fast though…. the cancer was eating him alive very rapidly.

Losing My Dad

On Sunday September 8, 2019, about half an hour before my 50th birthday, my dad passed away. My sister was with him when it happened, my mom and I went to the hospice to prepare my dad for the funeral. We scheduled the cremation in private for Thursday, since my flight back home was Saturday, with a public wake on Wednesday.

At this point, my mom was not eating well, and she was complaining about pain in the same area of her body as my dad. My sister and I were concerned, but we did not think it was anything super serious. We thought she just didn’t have much of an appetite because of the circumstances. She was declared clean just a couple of months ago, so we did not suspect anything serious.

It was almost as if she had kept up appearances though, because as soon as my dad died, my mom basically went to bed and didn’t come out. We thought she was just grieving, but after a couple of days it was clear that something was very wrong. An echo showed an enlarged liver, and she was scheduled to go back for a follow up on Friday, the day after my dad’s cremation. She was not healthy enough to come to the wake on Wednesday, and as we were getting ready to go to my dad’s cremation on Thursday, we had to call an ambulance to take my mom to the hospital. I cannot tell you how disturbing it is to be at your dad’s cremation while not knowing what is going on with your mom…

Losing My Mom

We did visit my mom in the ICU that night. She was dehydrated, undernourished, and all sorts of vital signs were not good. We were very anxious for the results of her tests, which we got the morning after.

Remember, this is the lung/oncology team that had initially treated my mom’s lung cancer, and then my dad’s lung cancer. My dad had passed away just a few days ago, and now my mom was in the ICU. When they walked into my mom’s room they all looked totally defeated, one of them even in tears. Her lung cancer had come back, and it had pretty much destroyed her liver. No more treatment was indicated. We talked about options for ‘making her as comfortable as possible’ (there’s that fucking word again), and my mom decided that she did not want to go to the hospice, she wanted to stay in the hospital. This was Friday morning September 13.

Unfortunately, there was no time for my mom to visit with any friends or family. She was so far gone that we couldn’t even have a proper conversation with her anymore. Just two days later, on Sunday September 15, she passed away, less than a week after my dad.

Within less than one week, I lost both my parents, to fucking lung cancer.

Three More Weeks

There was no way that I was going to leave my sister to deal with this by herself, so I extended my stay in Holland, and I spent another 3 weeks there.

My parents’ house was just an empty shell, just a building with furniture and all the stuff that they had collected over the span of their lives. We had to arrange for my mom’s cremation, and then the estate. It is SO strange to go around and ask friends and family if there are any things that they would like to have, things that have meaning to them. There were instruments for people that used to play with my dad. Paintings that my mom had made with sentimental meaning to certain people. One of my friends has a son in college, and we gave pretty much all of the kitchenware to him, in case he decides to move out. We were very lucky that we did not have any big conflicts, there were no fights over any tangible items.

We did not have a wake for my mom, we were just not up for it. We did end up arranging a spot in the ‘urn garden’ at a cemetery close to where they lived, and my sister arranged fora very nice plaque to commemorate them.

Update Feb 3, 2020: Added images

The rest of those three weeks my sister and I spent a LOT of time together, did some of the estate planning, and I ate away my misery.

Life Goes On

So… what now? I don’t know, to be honest. I have about 20 pounds to lose so I should probably start exercising and eating better. I live in one of the most beautiful places on earth, so there are lots of hiking options available. Maybe I’ll start listening to audio books instead of reading the utterly depressing news.

One thing that I realized is that people can be real human beings. These past 5 weeks I was surrounded by SO MUCH love. So many people reached out to send us support, and I cannot tell you how much that meant to me and my family. The meal service from my sister’s coworkers was such a heart warming gesture, they really put a ton of love in all of those dishes. Spending a ton of time with my sister was very good for me. It was great to get to know her family much better, and my niece and I are very close as well as a result.

As for the community… Hopefully you’ll understand that I didn’t have it in me to do much of anything, I’ve had other (more important) things on my mind. The demise of CRS (it really does not exist anymore beyond the personal company of one of the ‘partners’) means that I don’t have direct access to a lot of the latest new stuff anymore from that side. The MVP program is not really organizing anything for the MVPs anymore, so there’s not a lot of new stuff coming from that direction. I do still have to figure out a ton of stuff for my clients, so I do have plenty to share. I’ll try to catch back up for the rest of this year, maybe the start of 2020 I’ll find some inspiration. I am thinking I might start creating short videos to supplement the blog, but if I do I want to make that into something nice. I don’t really know, I do want to pick this back up so stay tuned.

Anyway, this post turned out to be WAY longer than I planned, but once I started writing it just kind of fell out of my mind.

MVP Award Number 15

Today I received another MVP Award, the 15th in a row for me. I’m always proud of the moment that I see the email, and this year’s was not any different. Thanks to Microsoft for the recognition, and thanks for the community for continuing to make me feel welcome. I am going through some difficult medical things for me and for my immediate family, so I’m afraid I will not be able to make many contributions for the foreseeable future. I might write about that at some point but for now I’ll keep it to myself.

Extending the AL Language

Over the past year, I’ve taught many people how to develop extensions for Business Central using Visual Studio Code. Usually I try to keep the workshop to standard features in VSCode and the standard AL Language extension. One of the things I don’t usually cover in any detail is an additional extension that extends that language, the “CRS AL Language Extension”. Since I am one of the owners of CRS, I could take part of the credit for it, but you should know that it was developed pretty much 100% by Waldo. If you want to read more about the extension itself, read Waldo’s latest blog post about it, he’s much better at explaining it than I am.

There are a bunch of really useful features in this extension, but I want to specifically mention a couple that I think are indispensable. In fact, I would bet quite a bit of money that Microsoft will include some of these features in the official AL Language sooner rather than later. It would really not even be necessary, since these extensions are all open source anyway.

Rename/Reorganize

The feature that I use the most myself is the rename and reorganize feature. The extension provides a way to set up how you want files to be organized, and what you want the naming convention to be. Personally I don’t really care all that much about the specifics of any particular convention, as long as what I am doing is consistent, so that at some point things will be in the same place for every project that you work on. I usually just leave the default settings in there, and I know exactly where to find my objects. Go here to read more about how you can customize it to your needs.

Run in Web Client

There are a few standard ways to run a page that you are currently working on. If you’ve added access to the page to a role center you can just start the web client and browse to the page. If this is not the case, you can use the Search feature and start your page from there. You could also set a startup object in launch.json, and when you start the web client from VSCode, it will open on that object. Waldo’s AL extension provides a really easy way to start the current object from the Command Palette, using the ‘Run current object’ command. In the new version of the extension, this command now also shows up in the status bar. Finally, you can right click an object and the ‘Run Current Object’ command can be selected from the context menu.

These two features are the ones that I use the most, and they alone are worth getting the extension. I could not do AL development work without this extension. Download this extension and use it. If you have ideas to make it better, let Waldo know, he loves getting feedback and making it better.

My Take on Using Docker

This past week, there was another post by my good friend Arend-Jan Kauffmann about using Docker directly on Windows 10 (what are you still doing here? Go read AJ’s post!). He had previously written about using Docker in a Hyper-V VM, and he has helped me understand how this all works a number of times. Just to be sure I mention this here, you can read all about the technical details on Tobias Fenster’s blog but that goes over my head very quickly.

The reason why I am writing this is because I am very reluctant to make the step to install Docker directly on my laptop. What works for me at the moment is where I have Hyper-V enabled on my laptop, and I have a VM with just Windows Server 2016 (creating one with Windows Server 2019 is very high on the todo list). My Docker is installed in a snapshot of that VM, and that is where I do all of my development work. I wrote about this before, read it here.

See… I am the king of screwing up my computer. If there is anything, ANYTHING, that will mess up my computer and render it absolutely useless, I WILL find it, and I will kill my computer (I am hearing that in Liam Neeson’s voice by the way). I have had to re-install my laptop so many times because of things that went wrong. When I have a problem like this in my VM, I don’t even spend any time trying to figure out what went wrong (that gives me a headache just thinking about it). All I need to do is delete the snapshot, create a new one, and I’m back up in a matter of minutes. All my dev work is in repos that I sync regularly, so I never have to worry about losing any work.

I’ve read about Docker straight on Windows 10, and it sounds very nice and easy to use. At the same time, I read blog posts and even Tweets that mention damage to the host OS from normal Docker operations, and I just KNOW that if I try it will happen to me. My reluctance to use Docker on Windows 10 directly does not come from wanting to stay in the past, but it is more from the knowledge that I’m going to screw up my computer.

Maybe I’m too cautious, but for now I will stick to my setup and continue to use Docker inside a VM. It works for me, and for now that’s good enough.

Docs on GitHub

Maybe you remember, last year I wrote about signing an App Package file, but that post was really about how I got to collaborate with someone at Microsoft, and one of the things we did was improve the online documentation for this topic.

At the time, I had noticed that there was a feedback button on each page in Docs, and underneath the feedback button it said something like ‘feedback is linked to GitHub Issues’, which led me to wonder if we’d ever see Docs in a repo that we could actually contribute to.

Now today, through a tweet by one of the managers at Microsoft, there was a link to a blog post about that very topic: here it is.

Just think how great this is! Not only do we get access to the source files of the actual documentation, we have a mechanism to contribute to the content. If you ever find yourself confused by any of the documentation, you can either leave your feedback on Docs, or you can make a change and submit a pull request to the repo itself! Either way, the actual system that is used to maintain the docs source files is also used to track issues, and you can create issues yourself in that very system!

This is what we call a BFD 🙂

Look Out for the Code Police

One of the coolest features in VSCode is the ability to check your code at design time for specific things. This post will explain how you can turn on code analysis, and how to get away with breaking the rules that it tries to enforce.

There are three things you have to know about code analysis: First, it is a feature that can be enabled and disabled at will. Second, there are sets of rules for specific purposes that you can turn on and off. Finally, you can define exceptions to those rules, and what to do when the code analyzer finds a violation of one of the rules. All three items are found in the user settings, and the exceptions are then stored in a separate file called a ‘ruleset.json’ file.

Open the user settings from the Command Palette. You will need to have different levels of scrutiny for different projects, like one client has an on premises implementation, and another is developing an app for AppSource. These must follow different sets of rules, so they get their own codeanalyzers. Since each project is different, I would say that you define the code analysis attributes at the workspace level. You can set these features up in the sort of UI rendering of user settings, but I like to see the json file in the editor and use Intellisense there.

The code analysis feature is turned on by setting “al.enableCodeAnalysis” to “true”. In the “al.codeAnalyzers” property, you can define which set of rules is enabled. The one you should always enable is the ‘CodeCop’, which enforces some basic syntax rules. Then, depending on whether you are doing development for AppSource or for a tenant specific extension you can choose either the ‘AppSourceCop’ or the ‘PerTenantExtensionCop’. You should not have both of those last two enabled at the same time, because some rules for AppSource don’t apply for PerTenant and vice versa.

In my settings.json, I’ve turned on code analysis, and I have enabled the CodeCop and the AppSourceCop. To show you what this looks like when code analysis finds a violation in a code editor I’ve created a very simple codeunit:

Code analysis doesn’t like my code, the CodeCop does not approve of using BEGIN..END for a single statement. Personally I don’t agree with that rule, because I always use BEGIN..END in IF statements, I make fewer mistakes that way. The rule is not really a big problem, because the squiggly line under my code is green. If I had violated a really important rule, like missing a prefix in a field name, it would have been red.

Lucky for me, I can define for myself how certain rules are handled. Note that the problems screen shows which rule is broken (number AA0005). Let me show you how you can define what happens.

First, you create a new .json file in your workspace, and you set it up to be a ruleset. I am calling mine ‘Daniel.ruleset.json’ and I am putting it in my workspace root. Here’s a screenshot of the ruleset file:

Under the “action” you can set what you want to happen when this rule is broken. I don’t like the rule at all so I want it to ignore this rule altogether so I’ve set it to “None”. All you have to do now is tell settings where to look for additional rulesets, like this:

The rule itself still works, I’ve just overridden its behavior to something that I like. Going back to my codeunit, there is no longer the annoying little squiggly line, and this violation is no longer listed in the problems window.

No problem, I’m happy 🙂

One word of warning about using the ruleset to create exceptions on AppSource rules. Some of these rules are there because they are required for acceptance into AppSource. For instance, you MUST give EVERY field name a specific prefix/suffix. You can turn this rule off, but if any of your fields is missing a prefix/suffix, your app will not be accepted. Be aware which rules you break, because the code police WILL find you eventually 🙂

NAV Techdays 2018 Recap

I started to write this post while flying across the Atlantic Ocean on the second of a three leg journey home, a BA flight from London to Phoenix. It has been a very long trip that started when I traveled to Holland for Directions EMEA in Den Haag at the end of October. Since Directions and NAV Techdays were relatively close together, I decided to just stay with my family in Holland for those 4 weeks rather than fly back and forth twice in less than a month. This has been the longest that I’ve ever been away from home, and I was SO ready to be back in my own house.

NAV Techdays ended last Friday, and it’s been another fantastic week, as we’ve come to expect. As far as I can tell, the attendees in my pre-conference workshop were happy with the content, I can’t wait to get the feedback and see what I can improve for next time.

As per usual, Luc has posted the videos in record time, less than a week after the event. The whole playlist can be found here, and I wanted to highlight some of my favorite sessions. One of the most important developments in current technology is machine learning and AI. Dmitry Katson and Steven Renders put together an awesome session to introduce machine learning to us. The award for most entertaining session goes to Waldo and Vjeko, who put on a concert and wowed the audience with some really cool content. I also want to point out the session about CI/CD, which is going to be one of the most important things for everyone that is serious about implementing a professional development practice. Of course, I have to also mention the Docker session, which is the technology that makes it all possible.

Furtunately, next year’s event is not scheduled on Thanksgiving, which is a national holiday here in the US, one that typically involves lots of friends and family, and lots of food. I’ve had to miss it the past couple of years, and each time I’ve been bummed to hear the stories of all the great meals and gatherings that my family got to have without me. Next year I’ll be home for Turkey Day!

Thanks for another super event, it’s one of my favorite weeks of the year.

Extensible Enums

The AL language has an object type called ‘enum’. This object type defines a list of possible values in the form of a set of key/value pairs, plus captions. You can then create a field in a table or table extension enum as its data type, and the field will provide the user with a drop down list of those values. Just like option fields, the database stores the numerical values of the enum in the field.

To define a new enum, you create a new .al file in which you define the enum as an object, and you list the options of the enum as follows:

Note that the ‘Extensible’ property is set to true, so it will be possible to extend the enum with additional options when the enum is used in other extensions.

To link a field in a table or a table extension, you define the field as an enum type field, and specify the enum name as part of the field definition. In the following screenshot we’re adding an enum type field to the Customer table in a new tableextension:

Now, in order for this enum to be extended, you would have the app that includes the enum as a dependency (which puts the original enum into the current app’s symbol references), and then you would create a new object called an ‘enumextension’, in which you define additional values.

Now when you look at the Customer Card, you can see all the values in the dropdown for the new field:

It is also possible to link an option field in C/SIDE to an enum in AL, as shown in the following screenshot:

When I learned about the extensible enum type, I was salivating at the thought that it would be possible to extend the available options in a ton of tables (type in sales/purchase line, account type in journals, entry type in ledgers to name just a few of them). It IS possible to do just that, and eventually the goal is to replace all option type fields in Business Central with enum type fields, it’s just that it comes with a crap ton of refactoring of existing code.

There is a lot of code that checks for all available option values, with an ELSE leg in the CASE statement for ‘other values’. All of that code will need to be refactored to allow for extended enums instead of just raising an error with an unrecognized value.

Now you know about enums, start using them instead of option type fields, and make them as extensible as possible.

Directions 2018 Recap

Today’s the last day of Directions EMEA 2018, which was in Den Haag in The Netherlands. This is the town where I was born, and since I haven’t lived in Holland for almost 20 years, it was kind of strange to be here on a business trip. The event was hosted in the World Forum, which used to be called ‘Het Congres Gebouw’ which translates to ‘The Conference Building’. I had never been there for any conference, but it used to also be the home of the famous North Sea Jazz Festival.

My contribution to both events (I did the same workshop and sessions for Directions in San Diego as well as Den Haag) were:

  • An all day workshop to introduce C/SIDE developers to extensions and VSCode. There was a great buzz around the room at both events. Last year there was a bit of anger about the direction of NAV, but now that is settled, I saw a lot of excitement about the new environment, and everyone was eager to learn new things.
  • App Source Test Drive. In San Diego I was a co-presenter with Mike Glue, one of my fellow MVPs, who has developed the only Test Drive experience that is currently in AppSource. He could not make it to Holland, so I did this session by myself in Den Haag.
  • Source Code Management. I was surprised at how busy this session was, there was pretty much a full at both events, and the audience in Den Haag even posed for the picture in this post, which was a lot of fun to do with them.

Other than being very busy with my own workshops and sessions, I was able to attend some sessions myself. The ones that I will remember most, and that I will want to learn much more about was the session about Machine Learning, and the session about CI/CD for Business Central development. Especially the latter one will be important, because if we want to do repeatable software on a bigger scale, we will need, we MUST, learn how to be more professional. The days of flying by the seat of your pants as a partner are over, we must all adapt and become the professionals that we’ve pretended to be for so many years.

During my sessions and workshops I asked almost every staff member who looks old enough to remember if they knew anything about the history of the rooms. I would have loved to be able to say that I shared a stage with some of the greats of jazz, leaving out the fact that there are decades between those performances of course. Unfortunately, nobody remembered, and there does not seem to be any history for the building that I can find. I did find old programs for NSJ, but nobody seems to know what the rooms used to be called.

Whether I can say I share the stage with anybody or not, it was cool to be in The Hague for this conference.