Navigating Microsoft Base and System Apps with VS Code Workspaces

Set up an environment where Go to References works across your AL extensions as well as Base and System Applications of Business Central.

Navigating Microsoft Base and System Apps with VS Code Workspaces
Photo by Anastasia Petrova / Unsplash

There are good old tools for finding references to C/AL table fields or methods such as Prism for C/AL, or GDT Where Used Tool which I find very useful even today. Customizing the standard Dynamics NAV application used to be the most common way of filling the gaps in the business processes implementation, and these tools were absolutely crucial to have in order to make the modification reliable and consistent across the entire application. The Go to Definition action was added to C/SIDE some time ago, but there is still no big help in finding all places where an object is used.

With the move to AL, VS Code became the main development environment. It has been widely used by software developers to write applications in almost any language, and therefore, it has all the necessary tools to make their daily work productive. As a Business Central developer, there is one feature of VS Code that I wish the AL Language extension had. When working with an extension, it would be very helpful if the Go to References action supported finding code references across the extension and the AL symbols.

Challenge

Let's imagine we have just run the AL: Go! command and created a new extension project.

New AL Project

We have a task that involves extending an object. Getting familiar with the object and its references first is a good idea before we can say how big our work is. For that, we press Ctrl and left-click on the "Customer List" to go to definition. The SourceTable of the page is Customer, and we'd like to see where it's used. We right-click on Customer and select the Go to References action. The figure below shows the not very exciting message saying that No references found for 'Customer'.

Finding references across symbols not supported

Of course, we can take the source code from the Business Central installation archive, extract it into a folder, and open it in VS Code as a second window to explore. And we may need another window if we need to dig further into the System Application to see examples of the Facade design pattern, for example, when we get bored. Wouldn't it be nice to have everything in one place? I hope it will be working sometime in the future but for now, let's see what we can do about it by using VS Code Workspaces.

Adding projects to VS Code workspace

A folder opened by VS Code is essentially a workspace. We're going to put together several folders, which will become a multi-root workspace. It's supported by the AL Language extension, so let's start by creating an empty folder and opening it. Then, we follow the menu File -> Add Folder to Workspace... and select the ALProject1 folder with the extension project we created earlier. The result now should look as follows.

Workspace created

Let's keep this workspace for future use and go to File -> Save Workspace As..., which will create a new code-workspace file.

Workspace saved

Your folder path might be different depending on your projects' locations.

If you want to keep just one set of symbols in the workspace, and this is a completely optional step, create an alpackages folder where we'll have our symbols to share across the projects of our workspace. By adding the al.packageCachePath path to the workspace settings, we let the AL compiler know where to look for the symbols. In my case, the path to the alpackages folder is C:\al\al-workspace\alpackages. It's important to have an absolute path so that all referenced projects refer to the same path.

After that, copy the symbols from our ALProject1\.alpackages folder to the workspace's package cache folder and reload VS Code (hit Ctrl+Shift+P to open Command Palette and type reload to find the Developer: Reload Window command) to finish the symbols setup. All red squiggly lines should go away now and our ALProject1 should be able to see the shared symbols. The window now should look as in the below figure.

Workspace packages cache path and symbols setup

Update 28/04/2022: Although knowing about the al.packageCachePath setting can be useful, symbols also can be downloaded for each of the added app separately, if we skip the previous step. The AL compiler seems to like symbols per app more.

Now things get even more interesting. Let's add the Base App source code.

The standard Business Central source code comes with the installation package. For this exercise, I'm following a tip from Arend-Jan Kauffmann given in a BC Professionals Discord channel. I'm going to clone Stefan Maroń's repository MSDyn365BC.Code.History. It is regularly updated when a major version is released. Its current size is more than 5 GB, which means cloning the repository will take some time. The fetched codebase can be very handy if we want to play with different localization or versions, we could just check out the dedicated branch.

I'm working with the Australian localization, therefore, once the repo is cloned, I check out the au-19 branch and add the Base App source folder (in my case, at C:\git\MSDyn365BC.Code.History\BaseApp\Source\Base Application) to our workspace. VS Code will process the new project addition for several minutes, there should be no errors as a result.

Base App added to workspace

If we try and Go to Definition of the Customer List page now, we'll end up on the Customer List.dal tab with the symbols source code as before. The trick of pointing to the Base App project in our workspace is adding the Base App as a dependency to the extension app. After updating our extension, the app.json file content will look as follows.

{
  "id": "583af059-c0cb-42e2-b2d8-eeb89e3ad67a",
  "name": "ALProject1",
  "publisher": "Default publisher",
  "version": "1.0.0.0",
  "brief": "",
  "description": "",
  "privacyStatement": "",
  "EULA": "",
  "help": "",
  "url": "",
  "logo": "",
  "dependencies": [
    {
      "id": "437dbf0e-84ff-417a-965d-ed2bb9650972",
      "name":  "Base Application",
      "publisher":  "Microsoft",
      "version": "19.1.0.0"
    }
  ],
  "screenshots": [],
  "platform": "1.0.0.0",
  "application": "19.0.0.0",
  "idRanges": [
    {
      "from": 50100,
      "to": 50149
    }
  ],
  "resourceExposurePolicy": {
    "allowDebugging": true,
    "allowDownloadingSource": false,
    "includeSourceInSymbolFile": false
  },
  "runtime": "8.0"
}
app.json with Base App as dependency

This is it! Now if we go to the Customer List page definition from our HelloWorld.al code, we'll get into the CustomerList.Page.al file! Now try using Go to Referfeces from the Customer List page reference in the page object.

References across workspaces

Right? There are references from our extension and Base Application. Now we're navigating!

If Base Application navigation is all you need, you could stop at this point. Although I'd like to say that System Application is something that we definitely need to check out. It's just beautiful, implemented as separate apps using interfaces. I'll add my C:\git\MSDyn365BC.Code.History\System Application\Source\System Application folder to the workspace and give it some time to cook.

Now let's imagine, we need to work with InStream or OutStream, the Temp Blob codeunit can help with that.

Temp Blob codeunit referenced

The Temp Blob codeunit is part of System Application. We get to the symbols code if we navigate to its definition at this point. It should be okay after updating our app.json again by adding the following dependency after a comma.

 {
   "id":  "63ca2fa4-4f03-4f2b-a480-172fef340d3f",
   "name":  "System Application",
   "publisher":  "Microsoft",
   "version":  "19.1.0.0"
 }
System Application dependency

The result should look as in the figure below.

System Application added as dependency

Finally, we can witness a great piece of documented source code if we go to the Temp Blob codeunit definition.

Temp Blob codeunit

Conclusion

Following the steps in this article, we have set up an environment where we can navigate across our extensions along with Base and System Applications. Our application can even be published from the workspace - just select the HelloWorld.al file on the list and hit F5.

The workspace can be a bit slow to work though. The good news is that this setup also works if we decide to open only our application folder for faster development when symbols are just enough. We can always return back to the VS Code workspace if we need better navigation without using any other tool.

If anything didn't work for you, or something could be done better, please let me know in the comments. Happy sailing!


There are a couple of tips that can help with the setup in specific cases.

Tip #1

Disabling VS Code extensions for the workspace can improve processing performance. The AL Language extension is a must-have, of course.

Tip #2

If you're developing against a localized Business Central version, ensure to use the source code for the country.

Tip #3

Ensure the source code in the referenced folders belongs to the same version as the symbols, or remove the app symbols with code in a workspace. For instance, if we put the Microsoft_System Application_19.1.31886.32889.app file into the alpackages folder, and System Application source code that we have in a workspace folder is of version 19.1.31886.32186, we might get confusing at the first sight errors.

Ambiguous .NET reference error

Adding a dependency in app.json to an existing app in the workspace removes the requirement to have symbols.