Guidelines for Partners
With the introduction of Business Central 2023 release wave 2, AL programmers were introduced with Namespaces. Namespaces are used to organize code into logical groups and hierarchies, preventing naming conflicts that can occur when libraries are combined. Meaning that by using namespaces in AL language we will be able to have multiple object level names within the solution.
Starting with Business Central 2023 wave 2, an AL file can be defined with a namespace at the top level:
It’s essential to note that an object can only belong to one namespace, but the same namespace can be used for multiple objects.
Rules to consider when using Namespaces
- You can only have one object of a kind with the same name in a module.
- You can only have one object of a kind with the same name in a namespace.
Namespace syntax rules
- A namespace should be globally unique.
- The first part of a namespace is tied to the developing organization or an individual, followed by a product name, and logical grouping within the product, such as for example, namespace BigCompany.SmartProduct.SomeProductArea. This supports the two purposes of namespaces – object name unique and logical grouping of related functionality.
- Use a stable and non-version specific name for the namespace. Changing the name of a namespace is a breaking change.
- The namespace name can be any valid AL identifier, and it can contain dots to indicate a hierarchy of namespaces.
Namespace case analysis
I created a “Customer Card” belonging to the Simplanova.Sales.Customer namespace. Note that there is a standard “Customer Card” page under Microsoft.Sales.Customer namespace in the base app. This means I created an object with a duplicate name but under a different namespace.
Now, I want to create a Customer List with the same namespace:
As seen, when defining the CardPageId property, Visual Code automatically uses the object from the same Custom namespace used for the “Customer Card” page. However, changing the namespace for the “Customer List” page results in an error:
There are two approaches solve this error:
1. Define a using statement for the object with the correct namespace:
2. Add namespace when writing CardPageId in front of the declaration:
Both approaches are correct, but the programmer should choose the one more suitable for their solution.
If, for any reason, simultaneous usage of the Microsoft.Sales.Customer and Simplanova.Sales.Customer namespaces occurs, it could lead to an ambiguous error:
This can be fixed by defining the namespace to be used in front of it:
Another interesting observation is that when attempting to create a table with a duplicate name but within a non-standard table, you get an error:
I tried creating a Customer table within a custom namespace in this example.
Everything was published correctly, but when I tried opening the standard Customers page list, I got an error:
Then I looked within the Event Viewer and saw the following message:
When looking at SQL Server Management Studio, I can see that a custom table was created:
The first is standard, the second is an extension, and the third is the custom one I created. I encountered the same error when creating duplicate named tables for other objects (Customer, Vendor, Item tables).
Another interesting aspect related to Namespaces is that Microsoft shared their PowerShell script for assigning multiple namespaces within specific folders. Documentation link. So, let’s try using the script:
Firstly, I created a project with an SRC folder containing subfolders: Pages, Tables, and XMLorts.
And I want to add namespaces with a script that Microsoft provides. Below, you can see that the page “Customer List” and table Customer don’t have a namespace (notice that these files are under different folders):
I want objects in the Pages folder to have the “Letvido.Module.Test” namespace and objects in the Tables folder to have the “Letvido. App.Test” namespaces. Therefore, I created a “.csv” file like this:
As seen, I defined only the folders I want to be changed, which are Pages and Tables in this example (I didn’t include the XMLports folder).
Below is the script I used, similar to the one provided by Microsoft, with the only modification being the delimiter changed from ‘;’ to ‘,’ to match the “.csv” file format:
param ( [Parameter(Mandatory=$true)] [string] $CsvMappingFile, [Parameter(Mandatory=$true)] [string] $BasePath, [ValidateSet("Add","Ignore")] [string] $License = "Ignore", [char] $Delimiter = "," ) $files = Import-Csv $CsvMappingFile -Delimiter $Delimiter $licenseText = "// ------------------------------------------------------------------------------------------------`r`n" + "// right (c) <insert copyright>.`r`n" + "// <Insert license>`r`n" + "// ------------------------------------------------------------------------------------------------`r`n" foreach ($file in $files) { $folder = $file.Folder $namespace = $file.Namespace $namespaceLine = "namespace $namespace;`r`n" $folderPath = Join-Path $BasePath $folder $alFiles = Get-ChildItem -Path $folderPath -Filter "*.al" -File -Recurse foreach ($alFile in $alFiles) { $path = $alFile.FullName $content = Get-Content $path -Raw if ($content.IndexOf($licenseText) -eq -1) { # The file doesn't a contain license statement if ($License -eq "Ignore") { $content = $namespaceLine + $content } else {$content = $licenseText + "`r`n" + $namespaceLine + $content # Add a license statement } } else { $content = $content.Replace($licenseText, $licenseText + "`r`n" + $namespaceLine) # Keep the license and add a namespace } $content | Set-Content $path -NoNewline } }
Then, I opened PowerShell as Administrator and ran the script:
You must provide paths for your “.csv” file and project folder where the “.csv” file defined folders can be found:
Here are the results after running the script:
Note that the page within the Pages folder has a different namespace compared to the table in the Tables folder, as defined in the “.csv” file.
An important consideration is that this script doesn’t check if the namespace already exists within the “.al” file, so it is possible that it would add another namespace if one already existed. Here are the results after I ran the script for the second time:
Before running the script, ensure there aren’t AL files within folders defined in the “.csv” files to which you don’t want to assign namespaces.
Conclusion
In conclusion, I believe that namespaces are a great change for the AL language, providing code clarity and aiding AL programmers in moving away from prefix and suffix usage.