Skip to content

Commit d76f421

Browse files
added more details to Batch documentation #112; fixes #117; replaced adal-node example with msal-node in the readme #83
1 parent 2866b41 commit d76f421

File tree

5 files changed

+341
-239
lines changed

5 files changed

+341
-239
lines changed

README.md

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ Upload a script as a JavaScript Web Resource, place on the entity form or refer
104104

105105
```js
106106
//DynamicsWebApi makes calls to Web API v8.0 if a configuration is not set
107-
var dynamicsWebApi = new DynamicsWebApi();
107+
const dynamicsWebApi = new DynamicsWebApi();
108108

109109
dynamicsWebApi.executeUnboundFunction("WhoAmI").then(function (response) {
110110
Xrm.Navigation.openAlertDialog({
@@ -128,61 +128,66 @@ npm install dynamics-web-api --save
128128
Then include it in your file:
129129

130130
```js
131-
var DynamicsWebApi = require('dynamics-web-api');
131+
//CommonJS
132+
const DynamicsWebApi = require('dynamics-web-api');
133+
134+
//ES6 Module
135+
import DynamicsWebApi from 'dynamics-web-api';
132136
```
133137

134138
At this moment DynamicsWebApi does not fetch authorization tokens, so you will need to acquire OAuth token in your code and pass it to the DynamicsWebApi.
135-
Token can be aquired using [ADAL for Node.js](https://github.com/AzureAD/azure-activedirectory-library-for-nodejs) or you can write your own functionality, as it is described [here](http://alexanderdevelopment.net/post/2016/11/23/dynamics-365-and-node-js-integration-using-the-web-api/).
139+
Token can be aquired using [MSAL for JS](https://github.com/AzureAD/microsoft-authentication-library-for-js) or you can write your own functionality, as it is described [here](http://alexanderdevelopment.net/post/2016/11/23/dynamics-365-and-node-js-integration-using-the-web-api/).
136140

137-
Here is a sample using `adal-node`:
141+
Here is a sample using `@azure/msal-node`:
138142

139143
```js
140-
var DynamicsWebApi = require('dynamics-web-api');
141-
var AuthenticationContext = require('adal-node').AuthenticationContext;
142-
143-
//the following settings should be taken from Azure for your application
144-
//and stored in app settings file or in global variables
145-
146-
//OAuth Token Endpoint
147-
var authorityUrl = 'https://login.microsoftonline.com/00000000-0000-0000-0000-000000000011/oauth2/token';
148-
//CRM Organization URL
149-
var resource = 'https://myorg.crm.dynamics.com';
150-
//Dynamics 365 Client Id when registered in Azure
151-
var clientId = '00000000-0000-0000-0000-000000000001';
152-
var username = 'crm-user-name';
153-
var password = 'crm-user-password';
144+
//app configuraiton must be stored in a safe place
145+
import Config from './config.js';
146+
import DynamicsWebApi from 'dynamics-web-api';
147+
import * as MSAL from '@azure/msal-node';
154148

155-
var adalContext = new AuthenticationContext(authorityUrl);
149+
//OAuth Token Endpoint (from your Azure App Registration)
150+
const authorityUrl = 'https://login.microsoftonline.com/<COPY A GUID HERE>';
156151

157-
//add a callback as a parameter for your function
158-
function acquireToken(dynamicsWebApiCallback){
159-
//a callback for adal-node
160-
function adalCallback(error, token) {
161-
if (!error){
162-
//call DynamicsWebApi callback only when a token has been retrieved
163-
dynamicsWebApiCallback(token);
164-
}
165-
else{
166-
console.log('Token has not been retrieved. Error: ' + error.stack);
167-
}
152+
const msalConfig = {
153+
auth: {
154+
authority: authorityUrl,
155+
clientId: Config.clientId,
156+
clientSecret: Config.secret,
157+
knownAuthorities: ['login.microsoftonline.com']
168158
}
159+
}
169160

170-
//call a necessary function in adal-node object to get a token
171-
adalContext.acquireTokenWithUsernamePassword(resource, username, password, clientId, adalCallback);
161+
const cca = new MSAL.ConfidentialClientApplication(msalConfig);
162+
const serverUrl = 'https://<YOUR ORG HERE>.api.crm.dynamics.com';
163+
164+
//function that acquires a token and passes it to DynamicsWebApi
165+
const acquireToken = (dynamicsWebApiCallback) => {
166+
cca.acquireTokenByClientCredential({
167+
scopes: [`${serverUrl}/.default`],
168+
}).then(response => {
169+
//call DynamicsWebApi callback only when a token has been retrieved successfully
170+
dynamicsWebApiCallback(response.accessToken);
171+
}).catch((error) => {
172+
console.log(JSON.stringify(error));
173+
});
172174
}
173175

174-
//create DynamicsWebApi object
175-
var dynamicsWebApi = new DynamicsWebApi({
176-
webApiUrl: 'https://myorg.api.crm.dynamics.com/api/data/v9.1/',
176+
//create DynamicsWebApi
177+
const dynamicsWebApi = new DynamicsWebApi({
178+
webApiUrl: `${serverUrl}/api/data/v9.2/`,
177179
onTokenRefresh: acquireToken
178180
});
179181

180-
//call any function
181-
dynamicsWebApi.executeUnboundFunction("WhoAmI").then(function (response) {
182-
console.log('Hello Dynamics 365! My id is: ' + response.UserId);
183-
}).catch(function(error){
184-
console.log(error.message);
185-
});
182+
try{
183+
//call any function
184+
const reponse = await dynamicsWebApi.executeUnboundFunction('WhoAmI');
185+
console.log(`Hello Dynamics 365! My id is: ${response.UserId}`);
186+
}
187+
catch (error){
188+
console.log(error);
189+
}
190+
186191
```
187192

188193
### Configuration
@@ -1011,7 +1016,7 @@ Batch requests bundle multiple operations into a single one and have the followi
10111016
* Provides a way to run multiple operations in a single transaction. If any operation that changes data (within a single changeset) fails all completed ones will be rolled back.
10121017
* All operations within a batch request run consequently (FIFO).
10131018

1014-
DynamicsWebApi provides a straightforward way to execute Batch operations which may not always simple to compose.
1019+
DynamicsWebApi provides a straightforward way to execute Batch operations which may not always be simple to compose.
10151020
The following example bundles 2 retrieve multiple operations and an update:
10161021

10171022
```js
@@ -1112,7 +1117,7 @@ dynamicsWebApi.executeBatch()
11121117

11131118
```
11141119

1115-
Note that the second response does not have a returned value, it is a CRM Web API limitation.
1120+
Note that if you are making a request to a navigation property (`collection: 'customerid_contact'`), the request won't have a response, it is an OOTB Web API limitation.
11161121

11171122
**Important!** DynamicsWebApi automatically assigns value to a `Content-ID` if it is not provided, therefore, please set your `Content-ID` value less than 100000.
11181123

@@ -1151,6 +1156,9 @@ dynamicsWebApi.executeBatch()
11511156

11521157
```
11531158

1159+
**Important!** Web API seems to have a limitation (or a bug) where it does not return the response with `returnRepresentation` set to `true`. It happens only if you are trying to return a representation of an entity that is being
1160+
linked to another one in a single request. [More Info and examples is in this issue.](https://github.com/AleksandrRogov/DynamicsWebApi/issues/112).
1161+
11541162
#### Limitations
11551163

11561164
Currently, there are some limitations in DynamicsWebApi Batch Operations:

0 commit comments

Comments
 (0)