I finally got my youtube setup running, here’s the first video, Hacks with the Query String.
Let me know in the comments if you like videos like this, or reach out to be on Twitter @eHougaard if you want to contact me.
In this video, Erik demonstrates a clever technique for passing data into Business Central through the browser’s URL query string. By leveraging a control add-in with a small amount of JavaScript, you can read query string parameters from the URL and feed them into your AL code — essentially creating a “poor man’s web services” approach for scenarios where full API integration isn’t available.
The Real-World Use Case
Erik begins by showing a practical example: the SharePoint Connector app. This app uses the OAuth protocol, which requires a redirect URL that calls back into Business Central with an access code. When the external authentication service redirects back to Business Central, the app intercepts the URL, reads the information supplied by the login process, and stores the access token — all through the URL.
This same technique can be applied in any scenario where you have a trusted environment (like an application on your PC) that doesn’t support fancy web services or OData, but can open a URL. By appending data as query string parameters, you can pass information directly into Business Central.
Setting Up the Project
Erik starts with a fresh AL project in Visual Studio Code, created with the AL:Go! command. One best practice he mentions is always adding the tenant ID into the launch.json file to avoid accidentally deploying to the wrong tenant, and specifying the sandbox name explicitly.
Creating the Receiving Page
The first step is to create a page that will receive and process the URL parameters. This is a simple page with a label and a user control:
page 50100 "Demo Page"
{
Caption = 'Demo Page';
UsageCategory = Lists;
ApplicationArea = All;
layout
{
area(Content)
{
label(Lbl)
{
Caption = 'Just to show we''re here!';
ApplicationArea = All;
}
usercontrol(url; urlhack)
{
ApplicationArea = all;
trigger GetDemo(Demo: Text)
begin
message('Value from URL = %1', Demo);
end;
}
}
}
}
The key element here is the usercontrol. On the page, it’s declared using the usercontrol keyword (even though the object type is called a controladdin — don’t ask, as Erik puts it). The trigger GetDemo receives a text parameter and displays it with a message. Because this is an event (trigger), the parameter represents data coming in to AL from JavaScript.
How Business Central URLs Work
Business Central runs entirely in the browser, which means you can navigate directly to specific objects using URL parameters. For example, to open page 50100:
https://businesscentral.dynamics.com/<tenant>/sandbox?page=50100
The clever insight is that browsers are forgiving — if you supply more parameters than needed, they’re simply ignored by the Business Central routing. So you can append your own custom parameters:
https://businesscentral.dynamics.com/<tenant>/sandbox?page=50100&Demo=HelloDemo
Business Central will load page 50100 and happily ignore the Demo parameter. But your JavaScript running inside the page can read it.
Building the Control Add-in
The control add-in is where the magic happens. It acts as the bridge between JavaScript (which can read the browser URL) and AL code (which can process the data).
controladdin "urlhack"
{
MinimumHeight = 1;
MinimumWidth = 1;
MaximumHeight = 1;
MaximumWidth = 1;
StartupScript = 'startup.js';
Scripts = 'script.js';
event GetDemo(Demo: Text);
}
A few important things to note about control add-ins:
- No object number: Control add-ins are a newer type of object in AL and don’t require an object number — a glimpse into a future without object ID ranges.
- Minimal size: Since we’re not displaying anything, the control is set to 1×1 pixel. It’s essentially invisible — we just need the ability to run JavaScript.
- Events, not procedures: Procedures defined on a control add-in cannot return values because they’re called asynchronously. There’s no way for Business Central to grab a return value. Instead, we define an event (
GetDemo) with parameters that represent data flowing from JavaScript into AL. - StartupScript vs Scripts: The
StartupScriptruns when the control add-in is loaded. TheScriptsproperty is for library code, third-party JavaScript libraries, or procedure implementations.
The JavaScript: Reading the Query String
The startup script is where we read the URL and invoke the AL event. The script.js file is essentially empty (just a placeholder), while startup.js contains the actual logic:
//
var urlParams = new URLSearchParams(window.location.search);
if (urlParams.has('Demo'))
{
Microsoft.Dynamics.NAV.InvokeExtensibilityMethod("GetDemo",[urlParams.get('Demo')]);
}
This is just four lines of meaningful JavaScript, and here’s what each part does:
new URLSearchParams(window.location.search)— Creates a structured collection from the query string portion of the current URL.window.location.searchreturns everything after the?in the URL.urlParams.has('Demo')— Checks whether theDemoparameter exists in the query string. This is important because if the page is opened normally (without the parameter), nothing should happen.Microsoft.Dynamics.NAV.InvokeExtensibilityMethod("GetDemo", [urlParams.get('Demo')])— This is the bridge call. It invokes the AL event namedGetDemoand passes the value of theDemoquery parameter as an argument. The parameters are passed as an array.
Testing the Solution
When the page is opened normally (without any extra query parameters), nothing happens — exactly as expected, since the JavaScript checks for the presence of the Demo parameter before invoking anything.
When the page is opened with the custom query parameter:
?page=50100&Demo=HelloDemo
Business Central displays the message: “Value from URL = HelloDemo”. The data has successfully traveled from the URL, through JavaScript, and into AL code.
The Chain of Events
Here’s a summary of the complete flow:
- A URL is opened in the browser with a custom query string parameter (e.g.,
&Demo=HelloDemo). - Business Central loads the specified page, which contains a user control.
- The user control is defined as a control add-in with a startup script.
- The startup JavaScript reads the URL using the
URLSearchParamsAPI. - If the expected parameter exists, JavaScript calls
InvokeExtensibilityMethodto fire the AL event. - The AL trigger on the page receives the value and can process it however needed.
Conclusion
This technique provides a lightweight way to pass data into Business Central through the URL — no web services, no APIs, no OData. It’s particularly useful for OAuth redirect flows (like the SharePoint Connector example), integrations with local desktop applications, or any scenario where you need a simple mechanism to push data into Business Central from an external source. The entire solution consists of a control add-in definition, four lines of JavaScript, and a page with a trigger — a small amount of code for a surprisingly powerful capability.