mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-08-06 09:26:52 +01:00
Fix lifecycle compatibility guidance (#93)
* Fix lifecycle compatibility guidance Correct high-confidence Business Central guidance and samples for upgrade tags, collectible errors, trigger semantics, obsoletion, events, interfaces, API contracts, and test transactions. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e05a43e7-6448-4d67-9c73-798523f5d945 * Address guidance review findings Gate SecretText guidance to BC23 and clarify that the collectible-error sample intentionally emits a message-only blocking aggregate. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e05a43e7-6448-4d67-9c73-798523f5d945 --------- Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
This commit is contained in:
parent
aca3986fd0
commit
5706959e4a
32 changed files with 201 additions and 104 deletions
|
|
@ -15,10 +15,13 @@ codeunit 50185 "Collect Errors Good Sample"
|
|||
until Item.Next() = 0;
|
||||
|
||||
if HasCollectedErrors() then begin
|
||||
CollectedErrors := GetCollectedErrors();
|
||||
// The default is false; true retrieves and clears the collection.
|
||||
CollectedErrors := GetCollectedErrors(true);
|
||||
// This blocking aggregate intentionally retains messages only.
|
||||
foreach CollectedError in CollectedErrors do
|
||||
ErrorText += CollectedError.Message() + '\';
|
||||
Message('The following must be fixed before posting:\%1', ErrorText);
|
||||
Error(ErrorInfo.Create(
|
||||
StrSubstNo('The following must be fixed before posting:\%1', ErrorText), false));
|
||||
end;
|
||||
end;
|
||||
}
|
||||
|
|
@ -30,8 +33,10 @@ codeunit 50186 "Collect Errors Item Check"
|
|||
trigger OnRun()
|
||||
begin
|
||||
if Rec.Description = '' then
|
||||
Error('Item %1 has no description.', Rec."No.");
|
||||
Error(ErrorInfo.Create(
|
||||
StrSubstNo('Item %1 has no description.', Rec."No."), true));
|
||||
if Rec."Unit Cost" <= 0 then
|
||||
Error('Item %1 must have a positive unit cost.', Rec."No.");
|
||||
Error(ErrorInfo.Create(
|
||||
StrSubstNo('Item %1 must have a positive unit cost.', Rec."No."), true));
|
||||
end;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
bc-version: [19..]
|
||||
domain: error-handling
|
||||
keywords: [collectible-errors, errorbehavior, collect, getcollectederrors, hascollectederrors, validation, batch]
|
||||
technologies: [al]
|
||||
|
|
@ -11,16 +11,16 @@ application-area: [all]
|
|||
|
||||
## Description
|
||||
|
||||
By default a procedure stops on the first `Error`, so a user fixing ten bad rows must rerun the operation ten times. The collectible-errors feature postpones error handling to the end of the call: a procedure attributed `[ErrorBehavior(ErrorBehavior::Collect)]` keeps running as errors occur and gathers them, so all failures can be presented together. The collected errors are read with `HasCollectedErrors()` and `GetCollectedErrors()` (which returns a `List of [ErrorInfo]`); `ClearCollectedErrors()` empties the buffer. This is a platform mechanism most LLMs are unaware of — they reach for a manually concatenated `Text` buffer or a temporary error table instead.
|
||||
By default a procedure stops on the first `Error`, so a user fixing ten bad rows must rerun the operation ten times. The collectible-errors feature postpones error handling to the end of the call: a procedure attributed `[ErrorBehavior(ErrorBehavior::Collect)]` keeps running as collectible errors occur and gathers them, so all failures can be presented together. `GetCollectedErrors()` returns a `List of [ErrorInfo]` for the handler to inspect, but does not clear the collection by default; pass `true` to retrieve and clear in one call, or call `ClearCollectedErrors()` explicitly after retrieving. A handler can copy record information into a custom error page as Microsoft Learn demonstrates, or deliberately format only the messages into a final blocking error as this article's sample does.
|
||||
|
||||
## Best Practice
|
||||
|
||||
Mark the orchestrating procedure `[ErrorBehavior(ErrorBehavior::Collect)]` and run each item's validation so one failure doesn't abandon the rest — typically by calling the per-item routine through `Codeunit.Run`. When the run finishes, inspect `HasCollectedErrors()` and surface `GetCollectedErrors()` to the user as a single list. Always handle the collected errors yourself: the platform's own guidance is that any errors still in the collected list when the procedure ends are concatenated into one dialog, which is hard for users to read.
|
||||
Mark the orchestrating procedure `[ErrorBehavior(ErrorBehavior::Collect)]` and run each item's validation so one failure doesn't abandon the rest — typically by calling the per-item routine through `Codeunit.Run`. When the run finishes, inspect `HasCollectedErrors()`, retrieve and clear the list with `GetCollectedErrors(true)`, and fail the operation with the collected messages. The sample intentionally produces a text aggregate and does not claim to retain record/field metadata in the final error. If that metadata is needed, map each `ErrorInfo` to a custom error UI before clearing, following the Microsoft Learn pattern. Do not replace validation failure with `Message`: clearing collected errors suppresses the platform failure, so the custom handler must still block the invalid operation.
|
||||
|
||||
See sample: `collect-validation-errors-with-errorbehavior.good.al`.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
Two shapes signal trouble. The first is hand-rolled accumulation — appending messages to a `Text` variable and showing them at the end — which reimplements the platform feature, loses each error's `ErrorInfo` structure, and skips telemetry classification. The second is applying `[ErrorBehavior(ErrorBehavior::Collect)]` but never calling `HasCollectedErrors`/`GetCollectedErrors`, so every collected error spills into the platform's concatenated end-of-procedure dialog. Detection: a `Collect` attribute with no matching `GetCollectedErrors` call, or a per-row loop that builds an error string by concatenation.
|
||||
Three shapes signal trouble. Hand-rolled accumulation reimplements collection and prevents the handler from receiving individual `ErrorInfo` values. A `Collect` procedure that never handles the collection falls back to the concatenated platform dialog. Finally, code that calls parameterless `GetCollectedErrors()`, assumes it cleared the list, and only shows a `Message` can both leave the errors collected and allow invalid processing to continue.
|
||||
|
||||
See sample: `collect-validation-errors-with-errorbehavior.bad.al`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue