Dynamics 365 Business Central: Integrate with Microsoft Dataverse via APIs (Not using the standard Dataverse connector)

Dynamics 365 Business Central

Hi, Readers.
Yesterday we discussed how to use OAuth 2.0 to connect Dataverse tables (APIs) in Postman (Using Grant type: Client Credentials, not Implicit) – Get, Patch, Post and Delete. Let’s look at some simple examples,

For Authentication and environment setup, please refer to yesterday’s post. It is strongly recommended to test all processes in Postman before customizing BC.

In this post, I would like to talk about how to integrate with Microsoft Dataverse via APIs (Not using the standard Dataverse connector).
PS: Business apps often use data from more than one source. Dataverse combines data into a single set of logic that makes it easier to connect Business Central to other Dynamics 365 applications. For example, Dynamics 365 Sales or your own application built on Dataverse. To learn more about Dataverse, go to What is Dataverse? We have discussed the following topics:

As a test, let me briefly share the requirements.
Use Dataverse standard API to synchronize the “account” table to BC. This time the fields only use the following four, Account Name, Main Phone, City, Website.

In addition, the Guid type field Account is used as the primary key in BC to associate values. (Hidden by default)

And the main table are maintained on the BC side, so it mainly meet the following two requirements

  • Get all the data of the “account” table in Dataverse from BC
  • Add, modify, and delete data in BC and synchronize it to the “account” table in Dataverse

Simple diagram:

Let’s get started.

1. Create a new table to store the data from the “account” table in Dataverse. As mentioned above, the primary key is “Account”, and the secondary key “Account Name” is used for sorting, which you can ignore.

2. Create a new list page to display the table data.

3. Create a codeunit to manage the code, including Authentication, Get, Insert, Update, and Delete logic.

Authentication: Using the information I mentioned in how to use OAuth 2.0 to connect Dataverse tables (APIs) in Postman (Using Grant type: Client Credentials, not Implicit) – Get, Patch, Post and Delete.

Access Token URLhttps://login.microsoftonline.com/d8f36038-1f93-4543-affc-5dc92b6ee871/oauth2/v2.0/token (Change it to your tenant ID)

Client IDa80c03cf-6ffa-4b6e-b2c8-6005310d3d87

Client SecretfME7Q~cAaSBhXMGZoHY3ei64nn1fxGpqF42mh

Scope: https://org2ffa63f6.api.crm.dynamics.com/.default (Note that Scope is different from BC)

Web API endpointhttps://org2ffa63f6.api.crm.dynamics.com/api/data/v9.2

I hardcoded it in this example, but you can add some settings to allow users to enter this information flexibly.

More details: Dynamics 365 Business Central: How to use OAuth 2.0 in AL with SecretText (Using codeunit 501 OAuth2)

Get:
Endpoint:

https://org2ffa63f6.api.crm.dynamics.com/api/data/v9.2/accounts?$select=name,telephone1,address1_city,websiteurl

PS: In order to be compatible with previous versions, I still use the old way to read the value in JsonObject. If you are BC26 or later, you can use the following new method
Business Central 2025 wave 1 (BC26): Overloaded JsonObject data type GetValue method (New methods access properties and array elements for JSON)

Then add an action on the list page to get the data.

Done.

Test video:

Insert (Post):
Endpoint:

https://org2ffa63f6.api.crm.dynamics.com/api/data/v9.2/accounts?$select=name,telephone1,address1_city,websiteurl

PS: To retrieve data from an entity you’re updating, you can compose your PATCH/Post request so that data from the created record is returned with a status of 200 (OK). To get this result, you must use the Prefer: return=representation request header.

If the Prefer header is not added, the following error will occur.

The data does not represent a valid JSON token.

And when inserting data, first insert it into the “Account” table of Dataverse, then get the returned Account id (Guid), and then insert it into the BC table as the primary key. In this way, the data of the “Account” table in Dataverse can be associated with this primary key.

PS: This requires setting the DelayedInsert property of the page to true

Test video:

Modify (Patch):
Endpoint:

'https://org2ffa63f6.api.crm.dynamics.com/api/data/v9.2/accounts(' + GraphMgtGeneralTools.GetIdWithoutBrackets(DataverseAccount.Account) + ')'

Please note, we need to get the id from Guid without brackets, more details: Dynamics 365 Business Central: How to quickly get the id from Guid without brackets.

If you forget to do this, the following error will be displayed.

400 {“error”:{“code”:”0x80060888″,”message”:”Bad Request – Error in query syntax.”}}

Test video:

Delete:
Endpoint: As in Modify (Patch), you need to pay attention to the brackets.

'https://org2ffa63f6.api.crm.dynamics.com/api/data/v9.2/accounts(' + GraphMgtGeneralTools.GetIdWithoutBrackets(DataverseAccount.Account) + ')'

PS:
1. Because there is no way to return a value after deleting data, do not try to read the response text after deleting it.

The data does not represent a valid JSON token.

2. If you encounter the following error when deleting, please confirm whether the roles you have granted include the table’s delete permission.

403 {“error”:{“code”:”0x80048306″,”message”:”user with id 9e531e38-0d3d-f011-b4cc-000d3a3800ca does not have DeleteAccess right(s) for record with id 9196309f-2f40-f011-b4cb-000d3a3800ca of entity Account. Consider assigning a role with the required access level to the user or team. For further troubleshooting, please work with a system administrator to use the Access Checker tool on this record: https://org2ffa63f6.crm.dynamics.com/main.aspx?forceUCI=1&pagetype=entityrecord&etn=account&id=9196309f-2f40-f011-b4cb-000d3a3800ca

Test video:

Very simple, using this way, users do not need a Dataverse license and can achieve real-time synchronization. The disadvantage is that each synchronized table needs to be customized. Although the standard connector is not that easy to expand, I recommend using standard features as much as possible. However, if you only synchronize one table, this method is also very efficient. Please choose the most suitable solution based on your needs.

Source Code: GitHub (Please note that the source code is for reference only, you can improve it according to your own needs)

END

Hope this will help.

Thanks for reading.

ZHU

コメント

Copied title and URL