Pourquoi l’étendue Parent échoue sur les tables virtuelles Business Central dans Power Pages (et ce qui fonctionne)
Par Fred Morin ·
Aussi en anglais : Why Parent scope fails on Business Central virtual tables in Power Pages (and what works)
Testé le 2 octobre 2026 avec Business Central 28.5 (bac à sable) et un site Power Pages sur le modèle de données amélioré. Power Pages sur les tables virtuelles Business Central est encore une fonctionnalité en préversion : tout ceci peut changer.
Un portail client sur Business Central, ça semble simple. Un client se connecte et voit ses commandes et ses factures. Pas celles des autres.
La première moitié est facile aujourd'hui : Power Pages peut lire Business Central en direct, au moyen des tables virtuelles Dataverse. La deuxième moitié, « pas celles des autres », c'est là que ça s'est gâté.
J'ai monté un petit portail pour l'essayer. Le modèle de sécurité qui semblait évident n'a pas fonctionné. Cet article donne l'erreur, la raison, la configuration qui fonctionne, et une limite à connaître avant de promettre quoi que ce soit à un client.
En bref, si vous êtes pressé
- Une chaîne d'autorisations d'étendue Parent, du contact au client BC puis aux commandes de vente, échoue à l'exécution.
- Ce qui fonctionne : une relation synthétique entre le contact et chaque table de documents BC, avec par-dessus une autorisation de table d'étendue Contact.
- Le prix à payer : un seul contact par client BC.
Le contexte
- Les tables BC Client, Commande de vente et Facture de vente sont rendues visibles comme tables virtuelles (
dyn365bc_customer_v2_0,dyn365bc_salesorder_v2_0,dyn365bc_salesinvoice_v2_0). - La table Contact de Dataverse a une colonne de recherche vers la table virtuelle Client de BC. La mienne s'appelle
fm_bccustomer. - Chaque utilisateur du portail est un contact, lié à un client BC par cette colonne.
L'objectif : un contact connecté voit les commandes et les factures de son client, et de personne d'autre, sans aucune étendue Globale.
Premier essai : une chaîne d'autorisations Parent
Les tables virtuelles arrivent avec des relations de Commande de vente et de Facture de vente vers Client. Cette chaîne semblait donc naturelle :
| Autorisation de table | Type d'accès | Relation |
|---|---|---|
| Contact | Soi-même (Self) | |
| Client BC | Parent (du contact) | Recherche du contact vers le client BC |
| Commande de vente BC | Parent (du client BC) | dyn365bc_customer_salesorders |
| Facture de vente BC | Parent (du client BC) | dyn365bc_customer_salesinvoices |
Power Pages a accepté les quatre autorisations. Les listes, elles, ne se sont pas chargées. Les deux affichaient ceci :
'dyn365bc_customer_v2_0' entity doesn't contain attribute with Name = 'contactid'
and NameMapping = 'Logical' (look up attribute by name is case-sensitive).

La liste des factures avec la chaîne d'autorisations Parent en place. Les en-têtes de colonnes se chargent, pas les lignes.
Pourquoi ça échoue
Il faut lire le message au pied de la lettre. Le portail cherche une colonne contactid dans la table Client de BC. Il a construit la jointure comme si le client avait une recherche vers le contact.
Dans ce modèle, la recherche va dans l'autre sens : c'est le contact qui pointe vers le client. La requête générée par le portail n'est pas valide dans ce sens, et toutes les listes qui dépendent de la chaîne échouent.
Je n'ai pas vérifié si le même sens échoue aussi avec des tables Dataverse ordinaires. Je peux seulement dire qu'il échoue ici.
Deux autres impasses, pour vous éviter de les essayer :
- L'étendue Contact directement sur le client BC est impossible. L'étendue Contact exige une relation dans laquelle la table à protéger pointe vers le contact. Le client BC ne pointe pas vers le contact.
- Une relation synthétique vers la table Client elle-même est refusée :
Type 'lookup' of referenced attribute 'fm_bccustomer' and type 'primarykey' of referencing attribute 'dyn365bc_customer_v2_0id' ... must match.
Ce qui fonctionne : une relation synthétique et l'étendue Contact
C'est la méthode du guide de Microsoft pour cette fonctionnalité. Une relation synthétique demande à Dataverse de traiter une colonne d'une table native et une colonne d'une table virtuelle BC comme une relation, même s'il n'en existe pas réellement.
1. Ajouter une clé secondaire sur Contact
Dans la table Contact, ajoutez une clé qui contient uniquement la recherche vers le client BC.
| Paramètre | Valeur |
|---|---|
| Table | Contact |
| Nom de la clé | fm_bccustomeronlykey (la vôtre portera votre préfixe) |
| Colonnes | fm_bccustomer |
Attendez que l'index de la clé passe à l'état Actif. Chez moi, il a fallu environ une minute et demie.
2. Créer une relation synthétique par table de documents
Dans l'application Business Central Configuration, ouvrez Table Relations et créez une ligne. Pour les commandes de vente :
| Champ | Valeur |
|---|---|
| Nom de la relation | fm_contact2salesorder |
| Table native | contact |
| Clé de la table native | fm_bccustomeronlykey |
| Table virtuelle | dyn365bc_salesorder_v2_0 |
| Colonne native | fm_bccustomer |
| Colonne virtuelle | dyn365bc_customer_customerid |
Faites la même chose pour dyn365bc_salesinvoice_v2_0.
Je les ai créées par l'API Web de Dataverse plutôt que dans l'application. Les lignes se trouvent dans la table dyn365bc_syntheticrelations :
POST /api/data/v9.2/dyn365bc_syntheticrelations
Content-Type: application/json
{
"name": "fm_contact2salesorder",
"dyn365bc_nativeentity": "contact",
"dyn365bc_nativeentitykey": "fm_bccustomeronlykey",
"dyn365bc_virtualentity": "dyn365bc_salesorder_v2_0",
"dyn365bc_referencedattribname1": "fm_bccustomer",
"dyn365bc_referencingattribname1": "dyn365bc_customer_customerid"
}
Dataverse affiche ensuite une nouvelle relation sur la table virtuelle. Attention au préfixe ajouté : dyn365bc_fm_contact2salesorder. C'est ce nom qu'il faut donner à l'autorisation de table.
3. Passer les autorisations de table à l'étendue Contact
| Autorisation de table | Type d'accès | Relation | Privilèges |
|---|---|---|---|
| Commande de vente BC | Contact | dyn365bc_fm_contact2salesorder |
Lecture |
| Facture de vente BC | Contact | dyn365bc_fm_contact2salesinvoice |
Lecture |
Attribuez les deux au rôle Web Utilisateurs authentifiés. Redémarrez le site ou attendez que son cache se rafraîchisse.
Le résultat
J'ai testé avec deux contacts, chacun lié à un client CRONUS différent :
- Le contact A a vu exactement les trois commandes ouvertes de son client, ainsi que ses factures enregistrées.
- Le contact B a vu trois autres commandes et ses propres factures.
- Aucun des deux n'a vu les lignes de l'autre.

Contact A : les trois commandes ouvertes de son client.

Contact B, même page, mêmes autorisations : trois autres commandes.
La liste des factures s'est aussi paginée correctement : huit pages pour un contact, cinq pour l'autre, ce qui correspond au nombre de factures dans Business Central.
Le hic : un seul contact par client BC
La première clé que j'ai essayée avait deux colonnes, la recherche vers le client et l'adresse de courriel, pour que plusieurs contacts puissent appartenir au même client. La relation synthétique l'a refusée :
Every attribute of entitykey 'fm_bccustomerkey' of referenced entity 'contact' must be mapped
to an attribute of the same type on the referencing entity 'dyn365bc_salesorder_v2_0'
Chaque colonne de la clé doit être mappée à une colonne de la table virtuelle. Une commande de vente n'a aucune colonne qui contient le courriel de l'utilisateur du portail. La clé ne peut donc contenir que la recherche vers le client.
Or une clé secondaire est unique. Deux contacts ne peuvent pas porter le même client dans cette colonne.
Pour une démonstration, ça passe. Pour un vrai portail B2B, où un client a habituellement plusieurs utilisateurs, c'est un problème de conception à régler avant de commencer. Je n'ai pas construit de solution de rechange, alors je n'en recommande pas ici.
Deux autres points qui vous feront gagner du temps
- La table Client de BC se retrouve sans autorisation à étendue limitée utilisable. Si aucune page ne la lit, ne lui donnez aucun accès en lecture.
- Les utilisateurs externes du portail n'ont pas de licence Business Central. BC exécute leurs requêtes sous une application Entra intégrée nommée Power Pages Authenticated External Users. Le guide de Microsoft demande de l'activer dans BC (Applications Microsoft Entra) et de lui donner des ensembles d'autorisations. Je l'ai fait avant mon premier test, alors je ne peux pas vous montrer ce que fait le portail sans elle.
Si vous construisez quelque chose de semblable aujourd'hui
| Approche | Résultat |
|---|---|
| Étendue Parent : contact, puis client BC, puis commandes et factures | Échec, erreur contactid |
| Étendue Contact sur le client BC | Impossible, aucune relation vers le contact |
| Relation synthétique vers le client BC | Refusée, types incompatibles |
| Relation synthétique du contact vers Commande de vente / Facture de vente, avec étendue Contact | Fonctionne |
Si vous tombez sur l'erreur contactid avec une table virtuelle Business Central, arrêtez d'ajuster les autorisations Parent. Créez la clé et les relations synthétiques, puis passez les autorisations à l'étendue Contact. Et comptez combien d'utilisateurs du portail chaque client aura avant de choisir ce modèle.
Si vous voulez que vos clients voient leurs propres données Business Central sans une licence chacun, parlons-en.