Lately I was working on some contributions for the Office 365 CLI, specifically on adding files and meta data. When you look at the different documentation available on uploading files and setting meta data on a list item, you come across the usual REST API methods (Files/Add and File/ListItemAllFields). Using both method will let you upload files and set metadata on the corresponding list item. One of the drawbacks on using these methods is that setting some types of meta data is cumbersome, like taxonomy, user and lookup fields. For instance, to update a taxonomy field you should construct an object in the following manner:
{
MetaData: {
__metadata: {
"type"
:
"SP.Taxonomy.TaxonomyFieldValue"
},
Label:
"1"
,
TermGuid:
"499FF84B-82F6-4098-BAAB-9466248EBD2F"
,
WssId: -1
}
}
Updating metadata using such constructs and especially when using multi value columns, is a tricky way of updating such fields.
Another drawback could be that if you use versioning on your document library, the above methods will create 2 versions when uploading a file and adding meta data. While working on the Office 365 CLI, I came across the ValidateUpdateListItem method. This is a method on a list item and can be used to update list items. The nice thing on this endpoint is it has a property called ‘bNewDocumentUpdate’. Microsoft documentation specifies:
bNewDocumentUpdate | Set to false to create a list item |
It wasn’t really clear to me what this property was actually doing, but after some more digging it is actually very similar to the UpdateOverwriteVersion method available on the server API. So when you use the ValidateUpdateListItem method and set the bNewDocumentUpdate property to true, it will call the UpdateOverwriteVersion method, which will update the item without incrementing the version. This will result in only 1 new version. Nice!
Specify field values
The ValidateUpdateListItem method lets you update meta data on a list item by adding a formValues array to the body of the REST API post request.
"formValues": [
{ "FieldName": "Title",
"FieldValue": "Item" }
],
"bNewDocumentUpdate": false
There isn’t very much documentation available around the ValidateUpdateListItem method and setting its field values for the different kind of field types the list items could have. Below I will sum-up the different kind of fields and its fieldValue format:
Taxonomy Field (single value):
Taxonomy Field (multiple values):
“TermLabel1|cf8c72a1-0207-40ee-aebd-fca67d20bc8a;TermLabel2|e5cc320f-8b65-4882-afd5-f24d88d52b75;”
Person Field (single value):
Person Field (multiple values):
Hyperlink Field:
Validation
{ "value": [
{ "ErrorMessage": null,
"FieldName": "Title",
"FieldValue": "Item",
"HasException": false,
"ItemId": 0 },
{ "ErrorMessage": null,
"FieldName": "Id",
"FieldValue": "1",
"HasException": false,
"ItemId": 0
}
] }
Summary
Using the regular ListItemAllFields Update REST API endpoint is sometimes cumbersome in providing the correct constructs of objects for the values of the meta data. Next to this the endpoint will create 2 versions of the item when using Versioning on the library. The ValidateUpdateListItem() method on the List Item object is much easier in providing the field values for the fields to update. Next to this it has an option to specify, if to only create 1 version for the update on the list item, after uploading a file. Last but not least it will give you a response in order to let you check if the updates on the fields where successful or not and give validation errors back to your user.
June 30, 2018 at 6:17 am
thanks for deep explanation
but how we should create fieldValue object for single lookup fields?
thanks in advanced.
LikeLike
July 6, 2018 at 12:28 pm
Hi Ali,
I think you should use the same format as for the single person field. Person fields are lookup fields technically spoken, so I would imagine it should work. I haven’t had time to test it though.
LikeLike
July 9, 2018 at 8:33 am
Regard lookups, it happened so, that I investigated the method recently and assembled almost all fields data types fingerprints together in last paragraph of the blog post https://www.linkedin.com/pulse/list-items-system-update-options-sharepoint-online-andrew-koltyakov/
Long story short:
// Lookups fields (single and multi-valued)
{ FieldName: ‘LookupField’, FieldValue: ‘2’ /* Item ID as string */ },
{ FieldName: ‘MutliLookupField’, FieldValue: [3, 4, 5].map(id => `${id};#`).join(‘;#’) },
LikeLike
July 9, 2018 at 7:12 pm
Thanks for this update Andrew! Nice blogpost!
LikeLike
October 22, 2018 at 10:45 pm
Thanks Robert! Very helpful, just one additional comment on behavior I recently discovered while working on what you’ve started, the Office 365 CLI file add command :). If a file is checked out then it will automatically check it in when bNewDocumentUpdate = true. If we look at the $medatada api we can see that we can supply even a checkInComment.
LikeLike
October 23, 2018 at 6:34 am
Tnx Velin for pointing that out. Good addition!
LikeLike
May 27, 2019 at 1:57 pm
Thanks Robert, I was able to fix an infinite flow loop challenge I had with your information!
LikeLiked by 1 person
November 28, 2019 at 10:19 pm
Could you help with this Guys?
I get an error trying to update “Author” (Created By) in my list to setup a security based on the owner.(The owner is me cause the flow runs with my name)
I use send an http request to a SharePoint as an action
I use the web link to my Sharepoint
The method is “POST”
the URL is:_api/web/lists/getbytitle(‘MyInitiatives’)/items([‘ID’]})/ValidateUpdateListItem
Accept and content-type: Application/json;odata=verbos
Body:
{
“FormValues”:
[
{
“FieldName”:”Author”,
“FieldValue”: “[{‘Key’:'[‘Responsable’]?[‘Claims’]}’}]”
}
]
,”BnewDocumentUpdate”:false
}
Here is the error I get:
{
“message”: “Not well formatted JSON stream.\r\nclientRequestId: 23d3d6a7-be0b-42fb-8a62-458797af916a\r\nserviceRequestId: fb5e1c9f-1048-a000-a744-46dc2ce00736”,
“status”: 400,
“source”: “https://xxxxxxxxx.sharepoint.com/sites/pwa/OptimOPE/_api/web/lists/getbytitle(‘MyInitiatives’)/items(137)/ValidateUpdateListItem”,
“errors”: [
“-1”,
“Microsoft.SharePoint.Client.InvalidClientQueryException”
]
}
LikeLike
July 10, 2020 at 4:38 am
If anyone has the same issue: try to add ‘()’ to the end of the URL.
So in above example it should be: _api/web/lists/getbytitle(‘MyInitiatives’)/items([‘ID’]})/ValidateUpdateListItem()
Helped me!
LikeLike
September 9, 2020 at 5:21 pm
Great input. Many thanks, Robert!
LikeLike
February 25, 2021 at 6:15 pm
Etag checking is not working for this API
LikeLike