What’s new in AL for Business Central 2024 Wave 2, The Hacker Edition!

It’s that time of year again; Halloween decorations are coming out, and we get the yearly “Wave 2” release of Business Central. In this video, I take a look at what’s new in AL for this wave, check it out:

https://youtu.be/HFWEzq-Fplo

Welcome to another “What’s New” deep dive! In this video, Erik explores what’s new in AL for Business Central 2024 Wave 2 (BC version 25, AL runtime 14) — and then does what he does best: decompiles the compiler DLLs to find features that didn’t make it onto the official announcement list. Let’s walk through everything covered.

Understanding the Wave Release Model

Before diving into features, it’s worth noting how Microsoft’s “wave” release model works. Over the past six months, Microsoft has been working on a collection of features, but they don’t necessarily ship everything on day one. BC 25.0 is available now, but some announced features won’t appear until 25.1 or 25.2. So when you read the release notes, keep in mind that not everything is immediately available.

An interesting milestone: the Business Central version number (25) has now overtaken the year (2024). Behind the scenes, we’re running AL version 14.

Performance Profiling with Scheduled Rules

Business Central already had client-side performance profiling, but now Microsoft has added Profiler Schedules. The idea is that a customer admin, consultant, support person, or developer can set up a specific schedule rule — for example, to profile a given user and session type for a given duration. Once the rule is defined and enabled, the server will trigger a profile each time the rule is met. At the end of the duration, profiling stops and the results can be inspected for performance issues.

Imagine setting this up so that every time a specific user starts a particular report, it gets profiled automatically. That’s a powerful diagnostic tool that removes the need for manual profiling sessions.

The Ternary Operator

This one is slightly controversial. AL now supports the ternary operator, which lets you use an if-like expression inline to produce a value. In AL, the traditional if statement is a statement — it doesn’t return a value. Now you can write:

D2 := (D = Today()) ? 0D : EndOfYear;

This single line replaces the equivalent four-line if/else block:

if D = Today() then
    D2 := 0D
else
    D2 := EndOfYear;

The syntax uses the classic ? : pattern borrowed from C-family languages (created in the 1970s, as Erik quips, when keyboards were slow and time was money). While there are cases where this is genuinely useful — for example, inline expressions on page fields or styles — it can become completely unreadable if you nest ternary operators inside each other. Use it judiciously.

One area where this could be especially handy is in page layout expressions, potentially allowing you to set styles inline without creating global variables. However, there are some limitations with ambiguous syntax when combining it with certain AL constructs.

Pull Extension Source from GitHub

You can now specify a GitHub repository in the app.json file, so when someone opens an extension from the web client using “Open Source in VS Code,” it can pull the repo automatically. While most developers will likely already have the repo cloned locally, it’s a nice quality-of-life improvement for onboarding and exploration scenarios.

Easier External App Dependencies via NuGet

This is a significant improvement. If you have a dependency on an AppSource app, getting the symbols has historically been annoyingly difficult — especially dealing with full symbols versus public-only symbols. Microsoft is now auto-creating NuGet packages with symbols for all AppSource apps. You’ll be able to pull symbols from NuGet in addition to downloading them from an environment.

This is currently being integrated into AL-Go for GitHub, but the approach should spread to other workflows as well.

The this Keyword for Codeunit Self-Reference

In most AL objects, you already had self-reference keywords like CurrReport, CurrPage, etc. But codeunits had no equivalent — you couldn’t reference the current codeunit instance from within itself. Now, with the this keyword, you can.

This matters because codeunits are increasingly used as object-like constructs. Before this change, if you were inside a codeunit and needed to pass yourself as a parameter to another method, you couldn’t do it. You’d have to create a separate codeunit variable. Now you can simply use this.

The this keyword also works on pages:

this.Update();
// is equivalent to
CurrPage.Update();

Full-Text Search Indexes on Table Fields

You can now specify a field to support full-text search at the table level, and there’s a new filter syntax to use it. This is a full-stack implementation — you declare the index on the field, and then use it with SetFilter via a new filter token: @* (percent-based full-text search syntax).

As Erik notes, it’s been a long time since we got new filtering syntax in AL. This is a welcome addition, especially for scenarios where you need to search across large text fields efficiently.

Restore Extensions on Failed Publishing

Anyone who has worked with extension dependency trees knows the pain: you publish something deep in the tree, and if it fails, all dependent extensions end up uninstalled with no easy way back. Now, if publishing from VS Code fails, the process will attempt to restore any previously installed extensions that were uninstalled and unpublished as part of the failed operation. If a full restore isn’t possible, the developer gets informed about which extensions could be restored and which ones failed.

Word Report Improvements

Significant work has been done on Word report layouts. New features include conditional content within Word reports (something that’s been sorely missed) and theme support, which allows you to change a report’s look and feel — colors, fonts, and styles — directly in Word by changing the Office theme from the Design tab.

Package Resources in Extensions

This is one of Erik’s most-requested features for years. If your app needs bundled data files — config packages, JSON files, binary resources, etc. — there’s been no good way to include them in the app file. The workarounds were either hosting files on a web server and downloading at runtime, or a hack involving packaging data as images in a JavaScript control add-in. Neither approach was practical or secure.

Now you can package resources directly in the extension and access them from AL code. Note: this is part of the wave and won’t be available until approximately December (25.3 or similar).

Type Testing, Casting Operators, and Interface Extensions

AL interfaces get two major enhancements:

  • Extend AL interfaces — You can now create an interface that extends one or more existing interfaces.
  • Type testing and casting operators — You can check whether an object implements a specific interface (using an is operator) and cast it to that interface type. This solves the problem of not knowing at runtime whether you’re dealing with the original interface or an extended version.

While these features are important from a programming paradigm perspective, Erik notes that most AL development today doesn’t heavily use interfaces outside of specific areas. That said, he uses them in his own projects — the SharePoint Connector uses interfaces for incoming document sources and document classification criteria, and his Cloud Replicator app uses interfaces for different database destinations.

Profile Extensions

You can now create a profile extension object to extend and customize profiles from other extensions. A straightforward but welcome addition to the extensibility model.

The Hacker Edition: Hidden Gems from Decompiling the Compiler

As is tradition, Erik decompiled the central DLLs in the AL compiler to see what’s lurking beneath the surface that didn’t make it into the official release notes.

Configuration Dialogue Page Type

Among the page types, there’s a new entry called Configuration Dialogue. The description reads: “Dialogue that asks the user for input to configure a process or automation.” This is distinct from the existing Prompt Dialogue (introduced in version 12) and from Navigate pages.

The feature is still under development — it can only be set if extensibility is set to false and cannot yet be used in extensions. But it hints at a future where there’s a dedicated page type for configuration workflows, separate from the wizard-style Navigate pages.

Date and Time Member Access

A subtle but convenient addition: you can now access date and time components using dot notation:

// Instead of:
Day := Date2DMY(D, 1);

// You can now write:
Day := D.Day;

// Similarly for time:
Hour := T.Hour;
Ms := T.Milliseconds;

Available members on Date include .Day, .Month, .Year, and .Week. Time gets .Hour, .Milliseconds, and likely .Minute and .Second as well.

Query SaveAsJson

This one has a fun backstory. In a previous video, Erik demonstrated that you could save a query as Excel or CSV, but not as JSON — and pointed out this seemed like an obvious gap. Apparently Microsoft watches these videos, because SaveAsJson is now available on queries. A small but practical addition that came directly from community feedback.

File Upload Row Action

There’s a reference to something called a File Upload Row Action in the decompiled code. Its exact purpose isn’t clear yet, but it’s worth keeping an eye on.

The Project Setup

For reference, here’s the app.json configuration used for exploring these features, targeting BC 25 with AL runtime 14.1:

{
  "id": "27b30fa5-54ff-41af-9ef5-bcd41dfc5377",
  "name": "WhatsNewinBC25",
  "publisher": "Default Publisher",
  "version": "1.0.0.0",
  "dependencies": [],
  "platform": "1.0.0.0",
  "application": "25.0.0.0",
  "idRanges": [
    {
      "from": 50100,
      "to": 50149
    }
  ],
  "resourceExposurePolicy": {
    "allowDebugging": true,
    "allowDownloadingSource": true,
    "includeSourceInSymbolFile": true
  },
  "runtime": "14.1",
  "features": [
    "NoImplicitWith"
  ]
}

Summary

BC 2024 Wave 2 brings a solid set of AL improvements. The headline features — ternary operator, NuGet-based symbol packages, full-text search, the this keyword, interface extensions, and resource packaging — address real developer pain points. But the hidden gems found by decompiling the compiler are equally exciting: the new Configuration Dialogue page type, dot-notation for Date and Time, and SaveAsJson on queries all hint at a platform that’s steadily maturing.

Several of these features are wave-gated, meaning they’ll roll out over the coming months. Stay tuned for deeper dives into individual features in future videos.