mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-08-06 17:36:53 +01:00
Add P0 integration and control add-in guidance
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 02baffe8-0600-430d-81fa-a9993685e7cb
This commit is contained in:
parent
9214f73819
commit
cf55246ecf
16 changed files with 526 additions and 12 deletions
|
|
@ -0,0 +1,3 @@
|
|||
function loadPackagedTemplate(url) {
|
||||
return $.get(url).done(renderTemplate);
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
function loadPackagedTemplate(url) {
|
||||
return $.ajax({
|
||||
url: url,
|
||||
xhrFields: {
|
||||
withCredentials: true
|
||||
}
|
||||
}).done(renderTemplate);
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: ui
|
||||
keywords: [control-add-in, packaged-resource, ajax, withcredentials, xhrfields, jquery]
|
||||
technologies: [javascript]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
# Load packaged control add-in resources with credentialed AJAX
|
||||
|
||||
## Description
|
||||
|
||||
JavaScript in a Business Central control add-in can load a static resource from its extension package with AJAX, but the request needs the Business Central context and cookies. Set `xhrFields.withCredentials = true`; shorthand calls such as `$.get` omit that setting and can work during development yet fail in production.
|
||||
|
||||
## Best Practice
|
||||
|
||||
Use an AJAX form that explicitly enables `withCredentials` whenever a control add-in requests a packaged static resource. Keep this rule scoped to resources served from the add-in package; it is not generic advice to attach credentials to arbitrary external requests.
|
||||
|
||||
See sample: `control-addin-package-resource-ajax-needs-withcredentials.good.js`.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
Using `$.get(url)` or an `XMLHttpRequest` without `withCredentials = true` to retrieve package content. The request can lack the context and cookies required by the Business Central service.
|
||||
|
||||
See sample: `control-addin-package-resource-ajax-needs-withcredentials.bad.js`.
|
||||
|
||||
## Source
|
||||
|
||||
[Control add-in object: Loading static resources using AJAX requests](https://learn.microsoft.com/dynamics365/business-central/dev-itpro/developer/devenv-control-addin-object#loading-static-resources-using-ajax-requests).
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
function startSendingRows(rows) {
|
||||
window.setInterval(() => {
|
||||
Microsoft.Dynamics.NAV.InvokeExtensibilityMethod(
|
||||
"StoreRows",
|
||||
[JSON.stringify(rows)],
|
||||
false);
|
||||
}, 100);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
const pendingChunks = [];
|
||||
let callInProgress = false;
|
||||
let transferHalted = false;
|
||||
|
||||
function sendRows(rows, maxArgumentsBytes) {
|
||||
if (transferHalted)
|
||||
throw new Error("Retry or discard the failed chunk before sending more rows.");
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
const chunks = [];
|
||||
let chunk = [];
|
||||
const argumentBytes = (payload) =>
|
||||
encoder.encode(JSON.stringify([payload])).length;
|
||||
|
||||
for (const row of rows) {
|
||||
if (argumentBytes(JSON.stringify([row])) > maxArgumentsBytes)
|
||||
throw new Error("A row exceeds the configured payload limit.");
|
||||
|
||||
const candidate = JSON.stringify([...chunk, row]);
|
||||
|
||||
if (argumentBytes(candidate) <= maxArgumentsBytes) {
|
||||
chunk.push(row);
|
||||
continue;
|
||||
}
|
||||
|
||||
chunks.push(JSON.stringify(chunk));
|
||||
chunk = [row];
|
||||
}
|
||||
|
||||
if (chunk.length > 0)
|
||||
chunks.push(JSON.stringify(chunk));
|
||||
|
||||
pendingChunks.push(...chunks);
|
||||
sendNextChunk();
|
||||
}
|
||||
|
||||
function sendNextChunk() {
|
||||
if (callInProgress || pendingChunks.length === 0)
|
||||
return;
|
||||
|
||||
callInProgress = true;
|
||||
const payload = pendingChunks[0];
|
||||
Microsoft.Dynamics.NAV.InvokeExtensibilityMethod(
|
||||
"StoreRows",
|
||||
[payload],
|
||||
false,
|
||||
() => {
|
||||
pendingChunks.shift();
|
||||
callInProgress = false;
|
||||
sendNextChunk();
|
||||
},
|
||||
() => {
|
||||
callInProgress = false;
|
||||
transferHalted = true;
|
||||
showTransferError();
|
||||
});
|
||||
}
|
||||
|
||||
function retryFailedChunk() {
|
||||
if (!transferHalted)
|
||||
return;
|
||||
|
||||
transferHalted = false;
|
||||
sendNextChunk();
|
||||
}
|
||||
|
||||
function discardFailedChunk() {
|
||||
if (!transferHalted)
|
||||
return;
|
||||
|
||||
pendingChunks.shift();
|
||||
transferHalted = false;
|
||||
sendNextChunk();
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
bc-version: [20..]
|
||||
domain: ui
|
||||
keywords: [control-add-in, invokeextensibilitymethod, success-callback, throttling, payload, reduced-functionality]
|
||||
technologies: [javascript]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
# Serialize control add-in AL calls and keep payloads small
|
||||
|
||||
## Description
|
||||
|
||||
`InvokeExtensibilityMethod` crosses from a control add-in into the Business Central service. Repeated calls that outpace AL execution fill the communication channel, trigger reduced-functionality warnings, and can be queued, throttled, or rejected; an oversized single payload can also be rejected immediately. The success and error callbacks exist so the add-in can bound this traffic.
|
||||
|
||||
## Best Practice
|
||||
|
||||
Send byte-bounded chunks and invoke the next AL event only from the previous call's completion callback. Handle the error callback and stop until the caller explicitly retries or discards the failed chunk. There is no universal safe threshold, so measure the serialized argument array, reserve transport headroom below the server's `ClientServicesMaxUploadSize`, and reject an individual item that exceeds the configured budget.
|
||||
|
||||
See sample: `control-addin-throttle-al-calls-and-payload-size.good.js`.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
Calling `InvokeExtensibilityMethod` on an interval without tracking completion, recursively creating intervals, or serializing an entire unbounded dataset into one call. These patterns can overwhelm the client-service channel or exceed the upload limit.
|
||||
|
||||
See sample: `control-addin-throttle-al-calls-and-payload-size.bad.js`.
|
||||
|
||||
## Source
|
||||
|
||||
[Control add-in performance best practices](https://learn.microsoft.com/dynamics365/business-central/dev-itpro/developer/devenv-control-addin-bestpractices), [InvokeExtensibilityMethod](https://learn.microsoft.com/dynamics365/business-central/dev-itpro/developer/methods/devenv-invokeextensibility-method), and [control add-in resiliency](https://learn.microsoft.com/dynamics365/business-central/across-controladdin-resiliency).
|
||||
Loading…
Add table
Add a link
Reference in a new issue