Skip to content

Commit 06103d8

Browse files
add: Use Content-ID inside a request payload; fix: type definitions
1 parent 58c3c8c commit 06103d8

File tree

6 files changed

+128
-12
lines changed

6 files changed

+128
-12
lines changed

README.md

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,13 +1037,13 @@ var order = {
10371037
};
10381038

10391039
var contact = {
1040-
firstname: "test content",
1041-
lastname: "id"
1040+
firstname: 'John',
1041+
lastname: 'Doe'
10421042
};
10431043

10441044
dynamicsWebApi.startBatch();
10451045
dynamicsWebApi.createRequest({ entity: order, collection: 'salesorders', contentId: '1' });
1046-
dynamicsWebApi.createRequest({ entity: contact, collection: 'customerid_contact', contentId: "$1" });
1046+
dynamicsWebApi.createRequest({ entity: contact, collection: 'customerid_contact', contentId: '$1' });
10471047

10481048
dynamicsWebApi.executeBatch()
10491049
.then(function (responses) {
@@ -1059,6 +1059,41 @@ Note that the second response does not have a returned value, it is a CRM Web AP
10591059

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

1062+
### Use Content-ID inside a request payload
1063+
1064+
`version 1.5.7+`
1065+
1066+
Another option to make the same request is to use `Content-ID` reference inside a request payload as following:
1067+
1068+
```js
1069+
1070+
var contact = {
1071+
firstname: 'John',
1072+
lastname: 'Doe''
1073+
};
1074+
1075+
var order = {
1076+
name: '1 year membership',
1077+
//reference a request in a navigation property
1078+
'customerid_contact@odata.bind': '$1'
1079+
};
1080+
1081+
dynamicsWebApi.startBatch();
1082+
dynamicsWebApi.createRequest({ entity: contact, collection: 'contacts', contentId: '1' });
1083+
dynamicsWebApi.createRequest({ entity: order, collection: 'salesorders' });
1084+
1085+
dynamicsWebApi.executeBatch()
1086+
.then(function (responses) {
1087+
//in this case both ids exist in a response
1088+
//which makes it a preferred method
1089+
var contactId = responses[0];
1090+
var salesorderId = responses[1];
1091+
}).catch(function (error) {
1092+
//catch error here
1093+
});
1094+
1095+
```
1096+
10621097
#### Limitations
10631098
10641099
Currently, there are some limitations in DynamicsWebApi Batch Operations:

lib/requests/sendRequest.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ function stringifyData(data, config) {
4848
stringifiedData = JSON.stringify(data, function (key, value) {
4949
/// <param name="key" type="String">Description</param>
5050
if (key.endsWith('@odata.bind') || key.endsWith('@odata.id')) {
51-
if (typeof value === 'string') {
51+
if (typeof value === 'string' && !value.startsWith('$')) {
5252
//remove brackets in guid
5353
if (/\(\{[\w\d-]+\}\)/g.test(value)) {
5454
value = value.replace(/(.+)\(\{([\w\d-]+)\}\)/g, '$1($2)');

tests/main-tests.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4785,6 +4785,60 @@ describe("promises -", function () {
47854785
expect(scope.isDone()).to.be.true;
47864786
});
47874787
});
4788+
4789+
describe("create / create with Content-ID in a payload", function () {
4790+
var scope;
4791+
var rBody = mocks.data.batchCreateContentIDPayload;
4792+
var rBodys = rBody.split('\n');
4793+
var checkBody = '';
4794+
for (var i = 0; i < rBodys.length; i++) {
4795+
checkBody += rBodys[i];
4796+
}
4797+
before(function () {
4798+
var response = mocks.responses.batchUpdateDelete;
4799+
scope = nock(mocks.webApiUrl + '$batch')
4800+
.filteringRequestBody(function (body) {
4801+
body = body.replace(/dwa_batch_[\d\w]{8}-[\d\w]{4}-[\d\w]{4}-[\d\w]{4}-[\d\w]{12}/g, 'dwa_batch_XXX');
4802+
body = body.replace(/changeset_[\d\w]{8}-[\d\w]{4}-[\d\w]{4}-[\d\w]{4}-[\d\w]{12}/g, 'changeset_XXX');
4803+
var bodys = body.split('\n');
4804+
4805+
var resultBody = '';
4806+
for (var i = 0; i < bodys.length; i++) {
4807+
resultBody += bodys[i];
4808+
}
4809+
return resultBody;
4810+
})
4811+
.post("", checkBody)
4812+
.reply(response.status, response.responseText, response.responseHeaders);
4813+
});
4814+
4815+
after(function () {
4816+
nock.cleanAll();
4817+
});
4818+
4819+
it("returns a correct response", function (done) {
4820+
dynamicsWebApiTest.startBatch();
4821+
4822+
dynamicsWebApiTest.createRequest({ collection: 'records', entity: { firstname: "Test", lastname: "Batch!" }, contentId: '1' });
4823+
dynamicsWebApiTest.createRequest({ collection: 'tests', entity: { firstname: "Test1", lastname: "Batch!", "[email protected]": "$1" }});
4824+
4825+
dynamicsWebApiTest.executeBatch()
4826+
.then(function (object) {
4827+
expect(object.length).to.be.eq(2);
4828+
4829+
expect(object[0]).to.be.eq(mocks.data.testEntityId);
4830+
expect(object[1]).to.be.undefined;
4831+
4832+
done();
4833+
}).catch(function (object) {
4834+
done(object);
4835+
});
4836+
});
4837+
4838+
it("all requests have been made", function () {
4839+
expect(scope.isDone()).to.be.true;
4840+
});
4841+
});
47884842
});
47894843

47904844
describe("dynamicsWebApi.constructor -", function () {

tests/stubs.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,33 @@ var dataStubs = {
258258
'--changeset_XXX--\n' +
259259
'\n' +
260260
'--dwa_batch_XXX--',
261+
batchCreateContentIDPayload:
262+
'--dwa_batch_XXX\n' +
263+
'Content-Type: multipart/mixed;boundary=changeset_XXX\n' +
264+
'\n' +
265+
'--changeset_XXX\n' +
266+
'Content-Type: application/http\n' +
267+
'Content-Transfer-Encoding: binary\n' +
268+
'Content-ID: 1\n' +
269+
'\n' +
270+
'POST ' + webApiUrl + 'records HTTP/1.1\n' +
271+
'Content-Type: application/json\n' +
272+
'\n' +
273+
'{"firstname":"Test","lastname":"Batch!"}\n' +
274+
'\n' +
275+
'--changeset_XXX\n' +
276+
'Content-Type: application/http\n' +
277+
'Content-Transfer-Encoding: binary\n' +
278+
'Content-ID: 100001\n' +
279+
'\n' +
280+
'POST ' + webApiUrl + 'tests HTTP/1.1\n' +
281+
'Content-Type: application/json\n' +
282+
'\n' +
283+
'{"firstname":"Test1","lastname":"Batch!","[email protected]":"$1"}\n' +
284+
'\n' +
285+
'--changeset_XXX--\n' +
286+
'\n' +
287+
'--dwa_batch_XXX--',
261288
batchRetrieveMultipleDeleteRetrieveMultiple:
262289
'--dwa_batch_XXX\n' +
263290
'Content-Type: application/http\n' +

types/dynamics-web-api-callbacks.d.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Type definitions for dynamics-web-api-callbacks v1.5.6
1+
// Type definitions for dynamics-web-api-callbacks v1.5.7
22
// Project: https://github.com/AleksandrRogov/DynamicsWebApi
33
// Definitions by: Aleksandr Rogov https://github.com/AleksandrRogov/
44

@@ -590,7 +590,7 @@ declare namespace DynamicsWebApi {
590590
/**Sets Prefer header request with value "return=representation".Use this property to return just created or updated entity in a single request. */
591591
returnRepresentation?: boolean;
592592
/**BATCH REQUESTS ONLY! Sets Content-ID header or references request in a Change Set. */
593-
contentId: string;
593+
contentId?: string;
594594
}
595595

596596
interface UpdateRequestBase extends CRUDRequest {
@@ -609,7 +609,7 @@ declare namespace DynamicsWebApi {
609609
/**An Array(of Strings) representing the $select OData System Query Option to control which attributes will be returned. */
610610
select?: string[];
611611
/**BATCH REQUESTS ONLY! Sets Content-ID header or references request in a Change Set. */
612-
contentId: string;
612+
contentId?: string;
613613
}
614614

615615
interface UpdateRequest extends UpdateRequestBase {
@@ -632,7 +632,7 @@ declare namespace DynamicsWebApi {
632632
/**Sets If-Match header value that enables to use conditional retrieval or optimistic concurrency in applicable requests.*/
633633
ifmatch?: string;
634634
/**BATCH REQUESTS ONLY! Sets Content-ID header or references request in a Change Set. */
635-
contentId: string;
635+
contentId?: string;
636636
}
637637

638638
interface RetrieveRequest extends CRUDRequest {

types/dynamics-web-api.d.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Type definitions for dynamics-web-api v1.5.6
1+
// Type definitions for dynamics-web-api v1.5.7
22
// Project: https://github.com/AleksandrRogov/DynamicsWebApi/
33
// Definitions by: Aleksandr Rogov https://github.com/AleksandrRogov/
44

@@ -494,7 +494,7 @@ declare namespace DynamicsWebApi {
494494
/**Sets Prefer header request with value "return=representation".Use this property to return just created or updated entity in a single request. */
495495
returnRepresentation?: boolean;
496496
/**BATCH REQUESTS ONLY! Sets Content-ID header or references request in a Change Set. */
497-
contentId: string;
497+
contentId?: string;
498498
}
499499

500500
interface UpdateRequestBase extends CRUDRequest {
@@ -513,7 +513,7 @@ declare namespace DynamicsWebApi {
513513
/**An Array(of Strings) representing the $select OData System Query Option to control which attributes will be returned. */
514514
select?: string[];
515515
/**BATCH REQUESTS ONLY! Sets Content-ID header or references request in a Change Set. */
516-
contentId: string;
516+
contentId?: string;
517517
}
518518

519519
interface UpdateRequest extends UpdateRequestBase {
@@ -536,7 +536,7 @@ declare namespace DynamicsWebApi {
536536
/**Sets If-Match header value that enables to use conditional retrieval or optimistic concurrency in applicable requests.*/
537537
ifmatch?: string;
538538
/**BATCH REQUESTS ONLY! Sets Content-ID header or references request in a Change Set. */
539-
contentId: string;
539+
contentId?: string;
540540
}
541541

542542
interface RetrieveRequest extends CRUDRequest {

0 commit comments

Comments
 (0)