Sharepoint chiamate batch con JavaScript
Precedentemente ho mostrato un esempio su come usare l'API Rest di SharePoint Online per effettuare delle chiamate in batch con Power Automate.
La stessa cosa è fattibile anche con SharePoint 2016 o SharePoint 2019 on-premises con JavaScript usato nella pagina SharePoint.
La chiamata JavaScript è simile a questa
La variabile dataBatch andrà valorizzata in questo modo
Per un esempio di risposta vedi l'esempio in Creare item SharePoint in Batch con Power Automate.
In questo caso il corpo della richiesta HTTP in POST cambia
A questo punto è semplice valorizzare la variabile dataBatch
mentre la chiamata HTTP in JavaScript non cambia, è identica alla precedente.
Se tutte le letture sono sulla stessa lista si possono creare queste variabili
e costruire la stringa del body
Se invece le letture degli item sono su più liste, si può fare un array di oggetti
il codice si modifica l'eggermente
risultato
La stessa cosa è fattibile anche con SharePoint 2016 o SharePoint 2019 on-premises con JavaScript usato nella pagina SharePoint.
Scrittura
Ad esempio per inserire nuovi item si può usare, ed inviare, un body come questo in POSTText: Body richiesta HTTP per l'insert
--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb
Content-Type: multipart/mixed;boundary=changeset_6d3d8d17-488d-418e-a3a5-a8e4510d41ad
Content-Lenght: 570
Content-Transfer-Encoding: binary
--changeset_6d3d8d17-488d-418e-a3a5-a8e4510d41ad
Content-Type: application/http
Content-Transfer-Encoding: binary
POST /_api/web/lists/getbytitle('listName')/items HTTP/1.1
Content-Type: application/json;odata=nometadata
{"Title":"Batch 1"}
--changeset_6d3d8d17-488d-418e-a3a5-a8e4510d41ad
Content-Type: application/http
Content-Transfer-Encoding: binary
POST /_api/web/lists/getbytitle('listName')/items HTTP/1.1
Content-Type: application/json;odata=nometadata
{"Title":"Batch 2"}
--changeset_6d3d8d17-488d-418e-a3a5-a8e4510d41ad--
--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb--
Notare i tag --changeset_YYY usati come separatore tra le due insert o più in generale tra due o più update.
Mentre la chiusura è fatta tramite gli stessi tag seguiti da un doppio meno (--changeset_YYY-- e --batch_XXX--)
Mentre la chiusura è fatta tramite gli stessi tag seguiti da un doppio meno (--changeset_YYY-- e --batch_XXX--)
Rispetto all'esempio precedente, voglio evidenziare che le url possono essere anche relative ( /_api/web/lists/getbytitle('listName')/items) oltre che assolute.
La chiamata JavaScript è simile a questa
JavaScript: Chiamata HTTP
$.ajax({
type: "POST", // sempre solo in POST
url: "/_api/$batch", // url delle chiamata batch
data: dataBatch, // corpo della chiamata
contentType: "multipart/mixed;boundary=batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb",
headers: {
"accept": "application/json;odata=nometadata", // nometadata in alternativa a verbose, per non passare anche il tipo dell'item
"X-RequestDigest": $("#__REQUESTDIGEST").val(), // digest necessario per i POST
},
cache: false,
success: function (result) {
console.log("Result", result);
},
error: function (xhr, status) {
console.log("error", xhr, status);
}
});
Da notare che la url della API è relativa (/_api/$batch) in quanto questo esempio funziona solo all'interno di una pagina SharePoint.
il Content-Type della chiamata deve essere di tipo multipart/mixed;boundary.
il Content-Type della chiamata deve essere di tipo multipart/mixed;boundary.
La variabile dataBatch andrà valorizzata in questo modo
JavaScript: Variabile dataBatch
let dataChangesets = `
--changeset_6d3d8d17-488d-418e-a3a5-a8e4510d41ad
Content-Type: application/http
Content-Transfer-Encoding: binary
POST /_api/web/lists/getbytitle('listName')/items HTTP/1.1
Content-Type: application/json;odata=nometadata
{"Title":"Batch 1"}
--changeset_6d3d8d17-488d-418e-a3a5-a8e4510d41ad
Content-Type: application/http
Content-Transfer-Encoding: binary
POST /_api/web/lists/getbytitle('listName')/items HTTP/1.1
Content-Type: application/json;odata=nometadata
{"Title":"Batch 2"}
`;
let dataBatch = `--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb
Content-Type: multipart/mixed;boundary=changeset_6d3d8d17-488d-418e-a3a5-a8e4510d41ad
Content-Lenght: ${dataChangesets.length}
Content-Transfer-Encoding: binary
${dataChangesets}
--changeset_6d3d8d17-488d-418e-a3a5-a8e4510d41ad--
--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb--
`;
La proprietà nell'header Content-Lenght viene calcolata tramite la variabile ${dataChangesets.length}.
Per un esempio di risposta vedi l'esempio in Creare item SharePoint in Batch con Power Automate.
Lettura
La stessa API REST (/_api/$batch) può essere usata anche per fare più letture in contemporanea (batch) su una lista SharePoint.In questo caso il corpo della richiesta HTTP in POST cambia
Text: Body richiesta HTTP per le letture
--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb
Content-Type: application/http
Content-Transfer-Encoding: binary
GET /_api/web/lists/getbytitle('CalendarioCorsiFormazione_TipoCorso')/items(35) HTTP/1.1
Accept: application/json;odata=nometadata
--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb
Content-Type: application/http
Content-Transfer-Encoding: binary
GET /_api/web/lists/getbytitle('CalendarioCorsiFormazione_TipoCorso')/items(13) HTTP/1.1
Accept: application/json;odata=nometadata
--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb--
La prima cosa da evidenziare è che non va usato il separatore per i changesets.
Le varie chiamate in GET vanno divise con il separatore ---batch_XXX.
Le varie chiamate in GET vanno divise con il separatore ---batch_XXX.
Anche se facciamo delle letture in GET, la chiamata principale (/_api/$batch) è sempre in POST.
A questo punto è semplice valorizzare la variabile dataBatch
JavaScript: Varibile dataBatch letture multiple
let dataBatch= `--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb
Content-Type: application/http
Content-Transfer-Encoding: binary
GET /_api/web/lists/getbytitle('CalendarioCorsiFormazione_TipoCorso')/items(35) HTTP/1.1
Accept: application/json;odata=nometadata
--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb
Content-Type: application/http
Content-Transfer-Encoding: binary
GET /_api/web/lists/getbytitle('CalendarioCorsiFormazione_TipoCorso')/items(13) HTTP/1.1
Accept: application/json;odata=nometadata
--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb--
`;
Variante
Per semplicità si può semplificare la costruzione del body tramite un ciclo forEach.Se tutte le letture sono sulla stessa lista si possono creare queste variabili
JavaScript: Variabili
let listName = "MiaLista";
let itemsIds = [35, 12];
// template singola chiamata, esempio di lettura in GET
// con dei placeholder nella forma @nomeTag@
let template = `--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb
Content-Type: application/http
Content-Transfer-Encoding: binary
GET /_api/web/lists/getbytitle('@listName@')/items(@id@) HTTP/1.1
Accept: application/json;odata=nometadata
`;
JavaScript
var dataBatch = "";
itemsIds.forEach(id => dataBatch += template.replace("@listName@", listName).replace("@id@", id));
dataBatch += "--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb--\r\n";
La funzione JavaScript replace sostituisce solo la prima occorrenza della stringa indicata, per effettuare sostituzioni multiple vedi Javascript funzione replace.
da come risultatoText: Risultato
--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb
Content-Type: application/http
Content-Transfer-Encoding: binary
GET /_api/web/lists/getbytitle('MiaLista')/items(35) HTTP/1.1
Accept: application/json;odata=nometadata
--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb
Content-Type: application/http
Content-Transfer-Encoding: binary
GET /_api/web/lists/getbytitle('MiaLista')/items(12) HTTP/1.1
Accept: application/json;odata=nometadata
--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb--
Se invece le letture degli item sono su più liste, si può fare un array di oggetti
JavaScript: Variabili
let items = [
{listName: "Lista 1", id: 35},
{listName: "Lista 2", id:12}
];
JavaScript
var dataBatch = "";
items.forEach(item => dataBatch += template.replace("@listName@", item.listName).replace("@id@", item.id));
dataBatch += "--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb--\r\n";
Text: Risultato
--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb
Content-Type: application/http
Content-Transfer-Encoding: binary
GET /_api/web/lists/getbytitle('Lista 1')/items(35) HTTP/1.1
Accept: application/json;odata=nometadata
--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb
Content-Type: application/http
Content-Transfer-Encoding: binary
GET /_api/web/lists/getbytitle('Lista 2')/items(12) HTTP/1.1
Accept: application/json;odata=nometadata
--batch_c02f1b8d-deb1-486b-87db-d8ff6c7190cb--