Chapter 11: Extensions and Customizations
Objectives
By the end of this chapter you will be able to:
- Explain what an AL extension is and why it’s preferred over modifying base code
- Read and edit the main fields in
app.json - Create a permission set that grants access to your own objects
- Extend standard behavior with an event subscriber instead of changing base code
- Apply extension-packaging best practices you can defend in a code review
11.1 What is an extension?
Customizing Business Central used to mean editing Microsoft’s own source code directly. That was risky, and it made upgrades painful. An extension is a separate package of AL objects (tables, pages, codeunits, and so on) that adds or changes behavior without touching the base application’s code.
Everything you’ve built so far already lives inside an extension: the
Loan Repayment Schedule table, its page, and the Loan Repayment Mgt.
codeunit. This chapter is about packaging that extension properly and
extending other objects safely.
11.2 Anatomy of app.json
Every extension has an app.json manifest that describes what the
extension is and what it depends on.
{
"id": "b1f0c1a2-1234-4a1b-9c3d-1a2b3c4d5e6f",
"name": "Loan Repayment Management",
"publisher": "Your Company",
"version": "1.0.0.0",
"brief": "Track loan installments and repayment status.",
"idRanges": [
{
"from": 50100,
"to": 50149
}
],
"dependencies": [],
"runtime": "12.0"
}
Hint: If an object ID falls outside the range declared in
idRanges, the extension won’t compile. Reserve a range early and keep every object you create inside it.
11.3 Permission sets
Creating a table doesn’t automatically let anyone use it, because Business Central denies access by default. A permission set grants access to your objects as a named bundle that you can assign to users or roles.
permissionset 50100 "Loan Repayment"
{
Assignable = true;
Caption = 'Loan Repayment Management';
Permissions =
table "Loan Repayment Schedule" = X,
tabledata "Loan Repayment Schedule" = RIMD,
page "Loan Repayment Schedule List" = X,
codeunit "Loan Repayment Mgt." = X;
}
Hint: Access to a table’s rows is granted on
tabledata, withR,I,M, andDfor read, insert, modify, and delete.Xon a table, page, or codeunit only lets the user run or open that object; it doesn’t give access to any data. For a read-only reporting role, granttabledata ... = Rinstead ofRIMD. Don’t give everything full access just because it’s less to think about. That kind of blanket grant is exactly what a security review will flag.
11.4 Extending without modifying: event subscribers
Sometimes you want to react to something that happens in a standard object without touching that object. Microsoft publishes events for this, so you write a subscriber to the event instead of a modification.
codeunit 50101 "Loan Repayment Event Subscribers"
{
[EventSubscriber(ObjectType::Table, Database::Vendor, 'OnAfterInsertEvent', '', false, false)]
local procedure OnAfterInsertVendor(var Rec: Record Vendor)
begin
Message('New vendor %1 created — remember to check for outstanding loans.', Rec."No.");
end;
}
Hint: The
Messagehere is only for learning. In a real extension, a subscriber usually does something quieter, such as writing a log entry, creating a related record, or setting a default. A dialog popping up on every vendor insert would annoy every user in the company.
11.5 Best practices for extensions
- Reserve your ID range once and stick to it. Mixing ranges across extensions is a common cause of deployment conflicts.
- Grant the minimum permission needed:
Ron table data where read-only access is enough, andRIMDonly where users must change data. - Prefer event subscribers to any form of base-object modification. Subscribers survive Microsoft’s updates, and modifications don’t.
- Name each permission set so its purpose is obvious from the caption alone. “Loan Repayment Management” does that; “Custom Perms 1” doesn’t.
Chapter summary
In this chapter you:
- Learned why extensions replaced direct changes to base code
- Read the main fields of
app.jsonand what they mean - Created a permission set that grants access to your own objects
- Wrote an event subscriber that reacts to a standard table without modifying it
Tasks
- Write your
app.json. Create one for the Loan Repayment extension with anidRangesblock covering50100–50149, and confirm every object you built in Chapters 7–9 falls inside it. - Create the permission set. Add
permissionset 50100 "Loan Repayment"grantingRIMDon your table’s data andXon your table, page, and codeunit. - Add an event subscriber. Subscribe to
Vendor’sOnAfterInsertEvent(or another standard table’s insert event) and log or message something relevant to your extension. - Try it yourself. Your permission set currently grants full
RIMDaccess to the loan data. If you wanted a “read-only auditor” role that could view loan data but never change it, what would you change?
Check your work: compare your files against the reference solution in the Chapter 11 solutions.