Success!

Thank you for your message! We'll get back to you soon.

Your subscription to Learn Beyond BC newsletter has been received. Expect expert Business Central insights delivered to your inbox!

Subscribe to Newsletter

Get the latest Business Central insights delivered to your inbox!

Coming Soon!

This feature is coming imminently. Stay tuned!

Me, Myself and I are working hard to bring you something amazing.
Keep exploring and check back soon for updates!

Dynamics 365 Business Central: Extension Identity Using ModuleInfo in AL

BUSINESS CENTRAL 4 min read Aug 9, 2025

Dynamics 365 Business Central: Extension Identity Using ModuleInfo in AL

JB

Jeffrey Bulanadi

Software Artisan, Visionary & Reverse Engineering Architect

Published on August 9, 2025

0 views

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

Share this article

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...

Leave a Comment

Your email is secure and will never be published or shared.

Basic HTML tags supported

0/2000 characters

Community Guidelines

  • • Keep discussions professional and on-topic
  • • No spam, self-promotion, or off-topic content
  • • All comments are moderated before publication
  • • Technical questions are especially welcome!