derekfinlinson / xrm-webapi

Dynamics 365 Web Api TypeScript module
MIT License
27 stars 13 forks source link

Uncaught SyntaxError: Unexpected number in JSON at position 1 #25

Open cjsewell opened 6 years ago

cjsewell commented 6 years ago

Given I want to select multiple gets in a batch operation ( and I have PR #24 ) I receive the error

Uncaught SyntaxError: Unexpected number in JSON at position 1

What I expect is an array which contains the result of each inner response body.

Steps to reproduce:

const changeSets: any[] = [];

const gets: string[] = [
    "accounts?$select=name",
    "accounts?$select=name"
];

batchOperation(config, "BATCH123", "CHANGESET123", changeSets, gets)
    .then((result) => {
        console.log(result);
    }, (error) => {
        console.log(error);
    });

It appears xrm-webapi attempts to parse the entire response as JSON when first it should split and extract each individual response body first.

Example response from CRM that is passed to JSON.parse

--batchresponse_4534da94-ba24-4acb-b11e-3b35476dc3de
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 200 OK
Access-Control-Expose-Headers: Preference-Applied,OData-EntityId,Location,ETag,OData-Version,Content-Encoding,Transfer-Encoding,Content-Length,Retry-After
Content-Type: application/json; odata.metadata=minimal
OData-Version: 4.0

{
  "@odata.context":"https://dynamics.com/api/data/v8.2/$metadata#accounts(name)","value":[
    {
      "@odata.etag":"W/\"1248759412\"","name":"Account 1","accountid":"00000000-0000-0000-0000-000000000000"
    },{
      "@odata.etag":"W/\"1248759537\"","name":"Account 2","accountid":"00000000-0000-0000-0000-000000000000"
    }
  ]
}
--batchresponse_4534da94-ba24-4acb-b11e-3b35476dc3de
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 200 OK
Access-Control-Expose-Headers: Preference-Applied,OData-EntityId,Location,ETag,OData-Version,Content-Encoding,Transfer-Encoding,Content-Length,Retry-After
Content-Type: application/json; odata.metadata=minimal
OData-Version: 4.0

{
  "@odata.context":"https://dynamics.com/api/data/v8.2/$metadata#accounts(name)","value":[
    {
      "@odata.etag":"W/\"1248759412\"","name":"Account 1","accountid":"00000000-0000-0000-0000-000000000000"
    },{
      "@odata.etag":"W/\"1248759537\"","name":"Account 2","accountid":"00000000-0000-0000-0000-000000000000"
    }
  ]
}
--batchresponse_4534da94-ba24-4acb-b11e-3b35476dc3de--

The boundary separator can be extracted from the Content-Type response header. The response body should be split based on that. Per response body, the initial Content-Type and Content-Transfer-Encoding headers should be stripped out. The remaining HTTP headers should be parsed and checked ( e.g req.status >= 200) && (req.status < 300 ) If the response type is application/json the body should then be parsed by JSON.parse.

derekfinlinson commented 6 years ago

For now I just removed the JSON.parse while I work out parsing the actual response.