Latest Posts

Avoid concurrency using Etag in SharePoint REST-API Call

There’s always a chance of corrupting data if you have not handled the concurrency in your application. In this article, we will see how you can handle the situation when you are working with SharePoint REST-API calls.

Concurrency: When more than one person tries to update/delete the same resource, it is called concurrency effect.

This article is mainly focused on concurrency when you are working with SharePoint data using REST calls.

What is Etag / Entity Tag?

  • Etag is used as a version identifier of the resource and will be available in HTTP Response.
  • To handle concurrency situations, you can pass Etag in your HTTP request header.

How to check Etag value?

  1. When you get the REST API response, you can expand the metadata in results and find out one parameter called Etag. Refer to the screenshot below.
  2. check etag value in developer tools
  3. If you are getting only one element using a GET request, you will be able to get Etag using the code mentioned below.

    data.d.__metadata.etag;

  4. get Etag using code
  5. If you are getting multiple elements using a GET request, you will be able to get Etag using the code mentioned below.

    Here, i is the index of the row item in the result set.

    data.d.results[i].__metadata.etag

    multiple elements using GET request

How Etag is connected to concurrency?

I will try to explain this question using a simple example.

  • When you request the data from SharePoint to be updated, it comes with Etag as seen above.
  • This Etag specifies the current status or you can say the version of that resource.
  • Now, whenever you update the resource and if you try to get the Etag value, it will send you the updated value of Etag.
  • Thus, using Etag you can determine if the resource was modified or not between the timeline when you request the resource and when you update that resource.
  • Please refer below diagram to understand the situation.
  • etag concurrency diagram

How to solve the concurrency issues using Etag?

You need to modify your REST call for this.

  1. When you get (REST-API GET) the resource, you can store the Etag value of the resource in a hidden field.
  2. When you update/delete (REST-API POST) the data back, you can compare the stored Etag value with the Etag value of the resource. If both values match, then you can go ahead and perform your action.
  3. How to compare Etag values? - You can pass a header "IF-MATCH" in your REST API call. If the Etag values don’t match it will throw an error like below.

The request ETag value '' does not match the object's ETag value ','

Etag implementation example

Here we are going to update a list item. HTML and REST API code is given below. Comments are given to easily understand the code.

HTML Code

You can paste this code in to a Content Editor webpart

  • <button onclick="UpdateListItem();" type="button">Click mebutton>
  • <input type="hidden" id="hiddenField"/>

JavaScript Code

You can paste this code on the same page in Script Editor Web Part

  • function UpdateListItem() {
  •     GetItemId();
  • }
  •  
  • function GetItemId() {
  •     $.ajax
  •         ({
  •             // _spPageContextInfo.webAbsoluteUrl - will give absolute URL of the site where you are running the code.
  •             // You can replace this with other site URL where you want to apply the function         
  •             url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getByTitle('list name')/items?$filter=Title eq 'Item 1'&$top=1&$select=Id",
  •             type: "GET",
  •             headers:
  •             {
  •                 // Accept header: Specifies the format for response data from the server.
  •                 "Accept": "application/json;odata=verbose"
  •             },
  •             success: function (data, status, xhr) {
  •                 var dataresults = data.d.results;
  •  
  •                 // Assign Etag value to Hidden Field so that, later on, we can use it to compare
  •                 document.getElementById("hiddenField").value = data.d.results[0].__metadata.etag;
  •                 UpdateListItemUsingItemId(dataresults[0]["Id"]);
  •             },
  •             error: function (xhr, status, error) {
  •                 console.log("Failed");
  •             }
  •         });
  • }
  •  
  • function UpdateListItemUsingItemId(Id) {
  •     $.ajax
  •         ({  
  •             url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getByTitle('list name')/items(" + Id + ")",
  •             type: "POST",
  •             headers:
  •             {               
  •                 "Accept": "application/json;odata=verbose",
  •                 //Content-Type header: Specifies the format of the data that the client is sending to the server
  •                 "Content-Type": "application/json;odata=verbose",
  •                 // IF-MATCH header: Provides a way to verify that the object being changed has not been changed since it was last retrieved.
  •                 // "IF-MATCH":"*", will overwrite any modification in the object, since it was last retrieved.
  •                 // Here we are going to compare the Etag value of the retrieved item (stored in Hidden Field) to the Etag value of the same item which we are going to update
  •                 "IF-MATCH": document.getElementById("hiddenField").value,
  •                 //X-HTTP-Method: The MERGE method updates only the properties of the entity , while the PUT method replaces the existing entity with a new one that you supply in the body of the POST
  •                 "X-HTTP-Method": "MERGE",
  •                 // X-RequestDigest header: When you send a POST request, it must include the form digest value in X-RequestDigest header
  •                 "X-RequestDigest": $("#__REQUESTDIGEST").val()
  •             },
  •             data: JSON.stringify({
  •                 __metadata:
  •                 {
  •                     // Format of the "type" is: SP.Data.<>ListItem. First character of the <> should be in Capital
  •                     type: "SP.Data.List_x0020_NameListItem"
  •                 },
  •                 Description: "Updated Description"
  •             }),
  •             success: function (data, status, xhr) {
  •                 console.log("Success");
  •             },
  •             error: function (xhr, status, error) {
  •                 console.log("Failed");
  •             }
  •         });
  • }

Note:

  • In the above code, "IF-MATCH":"*" header will not compare any Etag value and will directly overwrite any modification in the object since it was last retrieved.
  • You can check REST API examples in order to work with the SharePoint object model.

Conclusion:

We went through a detail explanation about Etag and how we can use it to handle concurrency in SharePoint REST API programming.


We value your Feedback:

Page URL:

Name:

 

Email:

 
 

Suggestion:

 

© 2024 Code SharePoint