Know thy module. Build with awareness.
Yo! I’ve been busy crafting this site/blog as my new home base, moving away from LinkedIn as the main platform. But you’re here for another tutorial—learning above and beyond BC right? So let’s get down to business.
If you’ve been following our #BCSaturdayCodeHacks series, you already know: I'm building a lego masterpiece, one brick at a time, every Saturday. Each piece connects to something bigger. (Teaser post HAAHAHAHA)
Long story short, back when I was a BC Solution Architect at one of the aspiring ERP consulting firms in Singapore, one of my many tasks was to enhance their existing AppSource solution and PTEs. And one challenge stood out: knowing your app’s identity.
So how do you actually know your app’s identity? Let’s say you’re integrating with another system and need to check whether your extension is installed, published, or not. That’s where this powerful AL data type comes in that I'm about to introduce.
Say Hi to ModuleInfo, Our best friend in this situation.
So, What Is ModuleInfo?
In AL development, ModuleInfo is a powerful data type that allows your extension to introspect—accessing metadata about itself such as:
- Id (id in your app.json file)
- Name
- Publisher
- Version
- PackageId
- DataVersion
- Dependencies
This is especially useful when building modular, multi-extension environments or when you want your app to behave differently based on its own identity.
Now question, What are the use-case of this ModuleInfo
Use Case | Benefit |
---|---|
Diagnostics | Log which app triggered a process |
Modular Dev | Build shared libraries that adapt to host metadata |
Licensing | Validate publisher or AppId for premium features |
Setup Wizards | Show app name/version dynamically |
Multi-App Logic | Conditional behavior based on installed extensions |
Our Not So Booooooooring Part, Let’s Get Our Hands Dirty! Shall we, pleaseeeeeeeeeee?
Let’s say you’re building a module to register your app. The logic below follows a similar pattern.
procedure UpdateSubscriptionStatus()
var
LoremIpsumSetup: Record "JB Lorem Ipsum Setup";
DoJoLearnTxt: Label 'dojo@learnbeyondbc.com';
RegisteredSuccessMsg: Label 'You are now registered to use the %1.\\to activate, please reach out to %2', Comment = '%1 - App name, %2 - Contact Info for activation';
AppInfo: ModuleInfo;
begin
LoremIpsumSetup.Get();
LoremIpsumSetup.Registered := true;
LoremIpsumSetup."Last Updated" := CreateDateTime(Today, Time);
LoremIpsumSetup.Modify();
GetExtensionAppDetails(AppInfo);
Message(StrSubstNo(RegisteredSuccessMsg, AppInfo.Name, DoJoLearnTxt));
end;
procedure GetExtensionAppDetails(var AppInfo: ModuleInfo)
begin
NavApp.GetCallerModuleInfo(AppInfo);
end;
... which runs on let’s say our Activation/Serial Page.
page 50104 "JB Lorem Ipsum Setup"
{
<!-- Truncated. See the Github Demo -->
action(Register)
{
ApplicationArea = All;
Caption = 'Register';
Image = Register;
ToolTip = 'Register the Lorem Ipsum app.';
trigger OnAction()
begin
TryToRegisterOurNotSoBoringApp();
end;
}
local procedure TryToRegisterOurNotSoBoringApp()
var
ModuleInfoMgt: Codeunit "JB ModuleInfo Mgt.";
begin
ModuleInfoMgt.UpdateSubscriptionStatus();
end;
}
What this does is record your app info into the system—then you’re free to work your magic.
ModuleInfo Procedures
The code below demonstrates the available procedures and how to fetch dependencies for your app.
codeunit 50104 "JB ModuleInfo Mgt."
{
procedure GetExtensionAppDetails(var AppInfo: ModuleInfo)
begin
NavApp.GetCallerModuleInfo(AppInfo);
end;
#region Let's Try an Idea of Registering an App
procedure GetAppInfo(var AppInfo: ModuleInfo)
var
i: Integer;
DependencyJArr: JsonArray;
DependencyJObj: JsonObject;
AppInfoMsg: Label 'App Id: %1\Name: %2\Publisher: %3\Dependencies: %4', Comment = '%1 - App Id, %2 - App Name, %3 - App Publisher, %4 - App Dependencies';
DependencyInfo: ModuleDependencyInfo;
begin
GetExtensionAppDetails(AppInfo);
for i := 1 to AppInfo.Dependencies.Count() do begin
Clear(DependencyJObj);
DependencyInfo := AppInfo.Dependencies.Get(i);
DependencyJObj.Add('id', DependencyInfo.Id);
DependencyJObj.Add('name', DependencyInfo.Name);
DependencyJObj.Add('publisher', DependencyInfo.Publisher);
DependencyJArr.Add(DependencyJObj);
end;
Message(StrSubstNo(AppInfoMsg, AppInfo.Id, AppInfo.Name, AppInfo.Publisher, DependencyJArr));
end;
#endregion Let's Try an Idea of Registering an App
}
Here are the Best Practices, I can come up with:
- Centralize ModuleInfo usage in a helper codeunit for reuse across diagnostics, licensing, and setup flows.
- Validate extension Id and Publisher when gating premium features—don’t rely on extension name alone.
- Use Dependencies() sparingly in performance-critical flows; cache results if needed.
Gotchas to Watch For
- ModuleInfo doesn’t expose environment context—combine with Codeunit 457 for full awareness.
- Id may change across deployments if the extension is repackaged—ensure consistency in CI/CD.
- Dependencies procedure only reflects declared dependencies.
Talk is cheap. Code is proof. Let the demo do the talking! ✨
💀 Pro Tip
You can also use ModuleInfo.Dependencies() to loop through all dependency apps and build a dynamic registry or dependency map.
📣 Recap & What’s Next
Last week, we explored Environment Awareness using Codeunit 457 and Codeunit 433. This week, we turn inward—giving your extension the power to know itself.
Next Saturday, we’ll go even deeper into modular logic and runtime adaptability. Follow the journey. Build beyond.
♻️ Repost to support the community and follow Jeffrey Bulanadi for clear, technical insights above and beyond Business Central and AL development.
🔗 Demo Repository: Explore my GitHub sample showcasing the magic of ModuleInfo data type in AL: ModuleInfo on GitHub
Helpful Reference:
ModuleInfo Data Type – Microsoft Learn
#BCSaturdayCodeHacks #learnbeyondbc #Dynamics365 #MSDyn365 #MSDyn365BC #BusinessCentral #ALDevelopment #ALDev #DevTips #ConsultingLife #LearningBCNotSoBoringSeries
Join the Conversation
Share your thoughts, ask questions, or discuss this article with the community. All comments are moderated to ensure quality discussions.
Loading comments...
No comments yet
Be the first to start the conversation!
0 Comments
Leave a Comment