From eb15b295ea85d62f9af6dd6dfe35348683072571 Mon Sep 17 00:00:00 2001 From: Jesper Schulz-Wedde Date: Tue, 14 Jul 2026 12:31:25 +0200 Subject: [PATCH] Correct API part multiplicity guidance Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 02baffe8-0600-430d-81fa-a9993685e7cb --- ...api-parts-on-systemid-and-set-multiplicity.bad.al | 1 + ...pi-parts-on-systemid-and-set-multiplicity.good.al | 1 - ...ink-api-parts-on-systemid-and-set-multiplicity.md | 12 ++++++------ microsoft/skills/review/al-web-services-review.md | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/microsoft/knowledge/web-services/link-api-parts-on-systemid-and-set-multiplicity.bad.al b/microsoft/knowledge/web-services/link-api-parts-on-systemid-and-set-multiplicity.bad.al index 31e3c0a..a629672 100644 --- a/microsoft/knowledge/web-services/link-api-parts-on-systemid-and-set-multiplicity.bad.al +++ b/microsoft/knowledge/web-services/link-api-parts-on-systemid-and-set-multiplicity.bad.al @@ -19,6 +19,7 @@ page 50353 "WS Order API Bad" { EntityName = 'orderLine'; EntitySetName = 'orderLines'; + Multiplicity = ZeroOrOne; SubPageLink = "Order No." = Field("No."); } } diff --git a/microsoft/knowledge/web-services/link-api-parts-on-systemid-and-set-multiplicity.good.al b/microsoft/knowledge/web-services/link-api-parts-on-systemid-and-set-multiplicity.good.al index df0143f..4b7482a 100644 --- a/microsoft/knowledge/web-services/link-api-parts-on-systemid-and-set-multiplicity.good.al +++ b/microsoft/knowledge/web-services/link-api-parts-on-systemid-and-set-multiplicity.good.al @@ -23,7 +23,6 @@ page 50350 "WS Order API" { EntityName = 'orderLine'; EntitySetName = 'orderLines'; - Multiplicity = Many; SubPageLink = "Order Id" = Field(SystemId); } part(summary; "WS Order Summary API") diff --git a/microsoft/knowledge/web-services/link-api-parts-on-systemid-and-set-multiplicity.md b/microsoft/knowledge/web-services/link-api-parts-on-systemid-and-set-multiplicity.md index 1eecf61..7e759eb 100644 --- a/microsoft/knowledge/web-services/link-api-parts-on-systemid-and-set-multiplicity.md +++ b/microsoft/knowledge/web-services/link-api-parts-on-systemid-and-set-multiplicity.md @@ -1,5 +1,5 @@ --- -bc-version: [18..] +bc-version: [17..] domain: web-services keywords: [api-page, page-part, subpagelink, systemid, multiplicity, deep-insert, navigation-property] technologies: [al] @@ -7,24 +7,24 @@ countries: [w1] application-area: [all] --- -# Link API parts on SystemId and declare their multiplicity +# Link API parts on SystemId and choose the correct multiplicity ## Description -An API page part creates an OData navigation property and, for `Multiplicity = Many`, enables deep insert of child entities. When a custom parent API is keyed by its immutable `SystemId`, its child should carry a related GUID foreign key so the navigation constraint uses that same stable external identity. `Multiplicity` also controls whether metadata exposes an object (`ZeroOrOne`) or a collection (`Many`), so declare it deliberately instead of relying on the default 1:N relationship. +An API page part creates an OData navigation property and, for a 1:N relationship, enables deep insert of child entities. When a custom parent API is keyed by its immutable `SystemId`, its child should carry a related GUID foreign key so the navigation constraint uses that same stable external identity. Omitted `Multiplicity` validly defaults to 1:N collection metadata; set `ZeroOrOne` explicitly only when the part is intended to expose a singleton. ## Best Practice -Define the child foreign key as `Guid` with a `TableRelation` to the parent table's `SystemId`, then use `SubPageLink = "" = Field(SystemId)` on the parent API page. Set `Multiplicity = Many` for child collections and deep insert, or `Multiplicity = ZeroOrOne` for a singleton navigation property. +Define the child foreign key as `Guid` with a `TableRelation` to the parent table's `SystemId`, then use `SubPageLink = "" = Field(SystemId)` on the parent API page. For a child collection and deep insert, either use the documented default or declare `Multiplicity = Many`; for singleton metadata, declare `Multiplicity = ZeroOrOne`. See sample: `link-api-parts-on-systemid-and-set-multiplicity.good.al`. ## Anti Pattern -On a parent API with `ODataKeyFields = SystemId`, linking a child business field such as `"Order No."` to the parent's `"No."`, or omitting `Multiplicity` because the current default happens to produce a collection. The first creates a second identity scheme for navigation instead of using the contract's stable GUID; the second hides whether the contract intentionally exposes a singleton or collection. +On a parent API with `ODataKeyFields = SystemId`, linking a child business field such as `"Order No."` to the parent's `"No."` creates a second identity scheme for navigation instead of using the contract's stable GUID. A separate defect is an explicit multiplicity that contradicts the intended shape, such as `ZeroOrOne` on an order-lines collection or `Many` on a singleton. Omission alone is valid for the default 1:N collection. See sample: `link-api-parts-on-systemid-and-set-multiplicity.bad.al`. ## Source -[Developing a custom API](https://learn.microsoft.com/dynamics365/business-central/dev-itpro/developer/devenv-develop-custom-api) and [Multiplicity property](https://learn.microsoft.com/dynamics365/business-central/dev-itpro/developer/properties/devenv-multiplicity-property). +[Developing a custom API](https://learn.microsoft.com/dynamics365/business-central/dev-itpro/developer/devenv-develop-custom-api) and [Multiplicity property](https://learn.microsoft.com/dynamics365/business-central/dev-itpro/developer/properties/devenv-multiplicity-property). `Multiplicity` is available from runtime 6.3, shipped with Business Central 17.3; BC17 consumers therefore need update 17.3 or later. diff --git a/microsoft/skills/review/al-web-services-review.md b/microsoft/skills/review/al-web-services-review.md index f8c1537..6614dde 100644 --- a/microsoft/skills/review/al-web-services-review.md +++ b/microsoft/skills/review/al-web-services-review.md @@ -56,7 +56,7 @@ For each worklist entry, evaluate the diff against the file's `## Best Practice` - When the diff contains code that contradicts a Best Practice without being a full anti-pattern, emit `minor` with the same reference shape. - When the skill cannot detect a violation but the file is clearly applicable to the change, emit `info` citing the file. Repository-wide observations MAY omit `location`. -For API parts whose parent declares `ODataKeyFields = SystemId`, detect a child foreign key linked to a parent business field instead of `Field(SystemId)`, and an omitted `Multiplicity` where the diff defines the navigation contract. Do not apply the SystemId-link rule to APIs intentionally keyed by another field. For webhook eligibility, detect `QueryType = API`, `SourceTableTemporary = true`, composite `ODataKeyFields` (including an omitted property when a visible source primary key is composite), Job Queue Entry, and visible system-table sources; do not infer an unknown table number. For lifecycle code, require both create and renew paths to use a handler that returns the query-string `validationToken` verbatim with `200 OK`, and flag renewal scheduling that assumes subscriptions are permanent instead of using `expirationDateTime`. Do not emit generic HTTP or REST advice. +For API parts whose parent declares `ODataKeyFields = SystemId`, detect a child foreign key linked to a parent business field instead of `Field(SystemId)`. Do not apply the SystemId-link rule to APIs intentionally keyed by another field. Omitted `Multiplicity` is valid and means the documented default 1:N collection; never report omission alone. Report an explicit `ZeroOrOne` only when the changed contract clearly intends a collection or deep insert, and report an explicit `Many` only when it clearly intends a singleton. Singleton metadata requires an explicit `ZeroOrOne`. For webhook eligibility, detect `QueryType = API`, `SourceTableTemporary = true`, composite `ODataKeyFields` (including an omitted property when a visible source primary key is composite), Job Queue Entry, and visible system-table sources; do not infer an unknown table number. For lifecycle code, require both create and renew paths to use a handler that returns the query-string `validationToken` verbatim with `200 OK`, and flag renewal scheduling that assumes subscriptions are permanent instead of using `expirationDateTime`. Do not emit generic HTTP or REST advice. Set `confidence` to: