Before diving into the technical setup, here's what you should know about BC extensions:
They're not "customizations" in the traditional sense. Unlike older Dynamics NAV modifications where you changed the base code, BC extensions layer on top of the standard system. Think of them as add-ons rather than modifications.
They survive upgrades. This is huge. When Microsoft releases a new version of Business Central, your extensions typically continue working. No more dreading upgrade projects.
You don't need to be a programming wizard. While coding experience helps, I've seen accountants with basic Excel skills learn to build simple but useful extensions.
The learning resources are... scattered. Microsoft's documentation is improving but still leaves many practical questions unanswered. Community forums and blogs fill the gaps.
Let's skip the fluff and get your environment ready for actual development:
You'll need:
I recommend starting with a sandbox—it's easier to set up, and you won't need to mess with Docker configuration right away.
Pro tip: Also install these non-essential but incredibly helpful extensions:
Microsoft provides free 30-day sandboxes for development:
The secret step nobody mentions: Once your sandbox is running, you'll need to get the server URL to connect from VS Code:
Let's build something actually useful—a page extension that adds a customer's total sales to the customer card. Here's the step-by-step process:
The app.json
file contains your extension's metadata. Edit it to look something like this:
{
"id": "5d4f9c60-53c3-4e98-9c0f-ac3df063c1ad",
"name": "Customer Sales Info",
"publisher": "Your Company Name",
"version": "1.0.0.0",
"brief": "Shows total sales on customer card",
"description": "This extension adds total sales information to the customer card",
"privacyStatement": "",
"EULA": "",
"help": "",
"url": "",
"logo": "",
"dependencies": [],
"screenshots": [],
"platform": "1.0.0.0",
"application": "21.0.0.0",
"idRanges": [
{
"from": 50100,
"to": 50149
}
],
"resourceExposurePolicy": {
"allowDebugging": true,
"allowDownloadingSource": false,
"includeSourceInSymbolFile": false
},
"runtime": "10.0",
"features": [
"NoImplicitWith"
]
}
The parts that really matter:
Create a new file called CustomerCardExt.al
and add this code:
pageextension 50101 "Customer Card Ext" extends "Customer Card"
{
layout
{
addafter(Name)
{
field("Total Sales"; Rec.GetTotalSalesLCY())
{
ApplicationArea = All;
Caption = 'Total Sales (LCY)';
ToolTip = 'Shows the total sales for this customer.';
Editable = false;
}
}
}
}
Next, create another file called CustomerTotalSales.al
with this code:
codeunit 50101 "Customer Total Sales"
{
procedure GetTotalSalesLCY(CustomerNo: Code[20]): Decimal
var
SalesInvoiceLine: Record "Sales Invoice Line";
TotalAmount: Decimal;
begin
SalesInvoiceLine.SetRange("Sell-to Customer No.", CustomerNo);
SalesInvoiceLine.SetFilter("Type", '%1|%2', SalesInvoiceLine.Type::Item, SalesInvoiceLine.Type::Resource);
if SalesInvoiceLine.FindSet() then
repeat
TotalAmount += SalesInvoiceLine."Amount Including VAT";
until SalesInvoiceLine.Next() = 0;
exit(TotalAmount);
end;
}
Finally, add a table extension to add this method to the Customer table. Create CustomerExt.al
:
tableextension 50101 "Customer Ext" extends Customer
{
procedure GetTotalSalesLCY(): Decimal
var
CustomerTotalSales: Codeunit "Customer Total Sales";
begin
exit(CustomerTotalSales.GetTotalSalesLCY(Rec."No."));
end;
}
What just happened? You extended the Customer Card page to show a new field, added a method to the Customer table to calculate total sales, and created a codeunit to handle the calculation logic.
After creating dozens of extensions, here are the lessons that took me months to discover:
Don't put all your code in one file or even one extension. Create separate extensions for different functional areas:
This makes maintenance much easier and allows you to update parts independently.
Business Central is built on an event-driven architecture. Learn to:
// Example of subscribing to an event
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Sales-Post", 'OnAfterPostSalesDoc', '', false, false)]
local procedure OnAfterPostSalesDoc(var SalesHeader: Record "Sales Header")
begin
// Your code here runs after a sales document is posted
CreateCustomNotification(SalesHeader);
end;
My first extensions were painfully slow. I learned to:
// Bad performance
foreach Customer in Customers do
foreach SalesLine in AllSalesLines do
if SalesLine."Sell-to Customer No." = Customer."No." then
// Do something
// Better performance
foreach Customer in Customers do begin
SalesLines.SetRange("Sell-to Customer No.", Customer."No.");
if SalesLines.FindSet() then
repeat
// Do something
until SalesLines.Next() = 0;
end;
Learn these debugging techniques early:
Even for solo developers, use Git:
After wading through countless documentation pages and videos, these resources genuinely helped me improve:
Microsoft Learn's Business Central Development Path - Good for structured learning
Dynamics NAV / Business Central User Group (DUG) - The forum at dynamicsuser.net/bc has saved me countless hours
James Crowter's "Implementing Microsoft Dynamics 365 Business Central On-Premise" - Despite the title, it's excellent for cloud development too
Waldo's Blog - waldo.be has practical advice from a veteran BC developer
Kamil Sacek's AL Code Samples - github.com/kine/AL-Code-Samples shows real-world examples
Trying to port C/AL code directly to AL - The architecture is different; embrace extensions rather than fighting them
Ignoring Microsoft's application designs - Follow the patterns in the base application; they're there for a reason
Not testing with enough data - An extension that works with 10 records might fail with 10,000
Hardcoding business logic - Use setup tables to make your extensions configurable
Forgetting about permissions - Users need the right permissions to use your new functionality
Four years into my BC development journey, I'm still learning new techniques. The platform evolves rapidly, and each project brings new challenges.
If you're just starting, focus on:
Remember that every BC developer started where you are now. The learning curve might feel steep at first, but the ability to create custom functionality that perfectly fits your business needs makes it worthwhile.
Even better, the skills you develop are increasingly valuable as more companies adopt Business Central and need developers who can extend it to meet their specific requirements.
Explore insightful debugging techniques tailored for Business Central developers, aimed at improving code quality and streamlining business operations.
Kery Nguyen
2024-05-22
Get a deeper understanding of the landscape of blogs and communities for navigating Microsoft Dynamics 365 Business Central. Discover where to find precious resources, expert advice, and peer support.
Kery Nguyen
2024-03-10
Learn how to efficiently prepare your data for migration to Microsoft Dynamics 365 Business Central with these expert data cleanup strategies.
Matias Orlando
2024-01-15