What’s new in BC AL 2023 Wave 1, The Hacker Edition

It’s that time of the year again; Microsoft released a new version of the AL toolchain, and I poke behind the scenes to see what’s actually new. Check out the video:

https://youtu.be/SiYiYKsbT8w


In this late-night “Hacker Edition” session, Erik walks through the official list of what’s new in AL for Business Central 2023 Wave 1 (runtime version 11 / BC version 22), then fires up a decompiler to dig into the Microsoft DLLs and uncover undocumented changes lurking beneath the surface. Below is a comprehensive breakdown of everything covered.

AL Explorer and AL Home

The AL Explorer is a brand-new tool built into VS Code that lets you browse objects, events, APIs, and enums across your project and its loaded symbols. You can filter, group, bookmark favorites, and navigate directly to source code or run objects from the explorer.

Key Features of AL Explorer

  • Object browsing — View all objects in your app and referenced symbols
  • Event Explorer — Search for and discover events across the codebase
  • Path-based grouping — Microsoft has internally reorganized the source code in version 22, introducing paths like HR, Purchase, Blob Storage, Base64, etc. You can now group by path to see these new organizational areas
  • API browsing — See exposed APIs, though many remain hidden in “secret API apps” unless you have a dependency to them
  • Bookmarking — Mark your favorite objects for quick access

One important limitation: this is still not comparable to the old Object Designer in NAV where you could see everything in the system. Unless you add a reference to every single app, you’ll only see what’s part of your project’s symbol references.

AL Home is a startup page with information from the Microsoft Dev team. Erik has already turned it off since it opens every time — time will tell how often Microsoft actually updates the content there.

Better InStream Support

This is one of the more important changes. Previously, a stream could only be read once. If you needed to use the data twice, you had to stream it into a TempBlob or MemoryStream wrapper to reset the read pointer. Now you can reset directly on an InStream, plus get the current position and the length.

The decompiler confirms new methods on the InStream class:

  • ResetPosition — Reset the stream back to the beginning
  • Position — Get the current read position
  • Length — Get the total length of the stream

This is a significant improvement, especially when working with large binaries where avoiding extra memory allocations matters.

Code Action for Removing Application Area from Fields

A new code action lets you set the ApplicationArea property as a default at the page level rather than repeating it on every field. You can apply it across the current document, the entire project, or the whole workspace.

When applied, the ApplicationArea property is removed from individual fields and set once at the top level. Erik tested this and confirmed it works on runtime version 10 and up (not just 11).

Code Navigability on Event Subscribers

Previously, the event name in an event subscriber attribute was treated as a plain string rather than a navigable identifier. This has been fixed, making it easier to use Go to Definition and other navigation features on event subscriber declarations.

Control Database Locking Behavior

You can now set read isolation levels on a per-record basis. This enables scenarios like reading uncommitted data without the workarounds previously required. Erik references a previous video where he did “crazy stuff” with inter-thread communication using uncommitted data reads — this new feature could simplify those patterns considerably.

The decompiler reveals a new ReadIsolation property available on Record, RecordRef, and related types.

Define Regional Settings Per Report

Reports now have a FormatRegion property, allowing you to specify regional formatting settings per report. This is particularly useful in multi-language environments like Canada, where customers may need both English and French reports with different formatting — not just different text layers, but truly different regional conventions.

Folder Path for Control Add-in Resources

You can now use wildcard folder paths when specifying control add-in resources, rather than listing every file individually. This is a huge quality-of-life improvement when including JavaScript libraries with many files. The only missing piece is support for including subfolders recursively.

Here’s a sample showing a control add-in in use:

page 50100 "test"
{
    PageType = UserControlHost;
    layout
    {
        area(Content)
        {
            usercontrol(web; WebPageViewer)
            {
                trigger ControlAddInReady(CallbackUrl: Text)
                begin
                    this.CurrPage.web.Navigate('https://www.hougaard.com');
                end;
            }
        }
    }
}

Iteration with ForEach on Text Variables

A nice quality-of-life addition: you can now iterate over individual characters in a text variable using foreach. This requires runtime version 11:

var
    s: Text;
    c: Char;
begin
    s := 'INVOICE1000';
    foreach c in s do
        // process each character
        ;
end;

Actionable Error Dialogs

Error dialogs can now include custom action buttons with titles and captions. When you know the fix for an error — or at least where the user should navigate — you can provide a button that takes them directly there. Erik notes he plans to use this extensively in the Simple Object Designer, where validation errors during app deployment could offer a “fix it for me” button.

The decompiler confirms a new ErrorAction class with properties for specifying the method, title, and caption of the action.

Go to Implementation for Interfaces

Previously, navigating from an interface reference would jump to the interface definition rather than the implementing code. This navigation improvement lets you jump directly to the implementation — a straightforward quality-of-life fix.

IntelliSense Improvements

  • Temporary table indicator — Hovering over a record variable now shows whether it’s temporary
  • Enum ordinal value suggestion — When defining new enum values, the IDE suggests the next ordinal value

AppSource Improvements

Deploy Hotfixes for Older Versions

This addresses a real pain point for AppSource publishers. Previously, if you published version 5 of your app requiring BC22, customers still on BC21 were stuck on version 4 with no way to receive hotfixes. Now you can upload an intermediate version (e.g., 4.5) targeting BC21, so customers who haven’t yet upgraded still receive critical fixes.

Erik shares a personal example: he once added a dependency on something from version 20.4 in the Simple Object Designer, only to discover that many installations were still on 20.1 months later, leaving those users stranded on an older version.

Preview for AppSource Apps

Publishers can now generate true preview versions of their apps and distribute flight codes to customers for testing before going live. Previously the “preview” was limited to seeing the listing — not actually installing and trying the app.

Transactable Licensing

AppSource publishers can leverage Microsoft’s licensing infrastructure so users pay through Microsoft, which then passes the revenue through. This moves the ecosystem away from every app having its own licensing model.

Other Notable Changes

  • Multiple AL package cache paths — Support for multiple symbol cache locations, born from base app development needs
  • URLs in included rule sets — Rule sets can be hosted in a shared location rather than copied into every project
  • Attach debugger to next session — Debug a specific session by attaching to the next one that starts
  • AL-Go for GitHub — Continues to evolve; Erik plans a follow-up video
  • Pragma improvements — New rules and the ability to specify which disabled rule a pragma applies to

Undocumented Findings from the Decompiler

Erik’s decompiler dive revealed several items not prominently featured in the official documentation:

External Business Events (Power Platform Integration)

A new NavExternalBusinessEvent attribute allows exposing AL events as Power Platform events. This ties into the broader “Adopt faster with Microsoft Power Platform” initiative and enables tighter integration between Business Central and the Power Platform ecosystem.

Required Permissions Attribute

A new RequiredPermission attribute can be specified (likely on methods), along with an InheritPermissions property on objects. There’s clearly a lot of work happening around the permissions model.

IsInWriteTransaction

A new function IsInWriteTransaction lets you check whether the current code is executing within a write transaction. Erik notes this could come in handy for various scenarios.

Media and MediaSet Orphan Detection

Both Media and MediaSet classes now have a FindOrphans function, allowing you to detect orphaned media records — media that exists in the database but is no longer referenced by any record.

RecordRef Shared Temporary Records

You can now create a RecordRef that shares the same underlying data as a temporary record. This is a corner case, but when you need it, you really need it — for instance, when you have a temporary record and need to pass it as a RecordRef while maintaining access to the same set of records.

FindSet Overload Deprecated

The two-parameter overload of FindSet(true, true) is now deprecated on both Record and RecordRef. The second parameter (UpdateKey) has had no effect for a long time, so Microsoft is finally cleaning this up.

Additions in Runtime 10.1 and 10.2

Microsoft also played catch-up with some additions backported to earlier minor versions:

  • 10.1 — Per-user offer plan for entitlements; PrintOnlyIfDetail on reports
  • 10.2IsEntitled and IsUnlicensed properties on NavApp

Summary

Business Central 2023 Wave 1 brings a solid collection of developer-facing improvements. The highlights are the AL Explorer for object and event browsing, dramatically improved InStream support with position reset and length, actionable error dialogs, per-record read isolation levels, and ForEach iteration on text variables. On the AppSource side, the ability to deploy hotfixes to older versions and provide true preview builds addresses long-standing pain points for publishers.

The decompiler session revealed additional gems like Power Platform business event integration, media orphan detection, shared temporary RecordRef support, and the long-overdue deprecation of the ineffective FindSet UpdateKey parameter. As always, the official documentation tells most of the story — but not all of it.