Making Your REST Calls Simpler by Changing the Metadata Setting
When you talk to SharePoint using REST, you have some options about what the data you get or send looks like. Early on, when REST first arrived on the scene for SharePoint, we HAD to specify odata=verbose
. This meant that we had to be very specific about what our data was going to look like, especially when it came to updates.
If you don’t use odata=verbose
, then you’re telling the server to accept something different. You’re basically telling the server what “dialect” of odata you are choosing to speak for the current transaction.
If you look at this post, you’ll see the options:
https://blogs.office.com/2014/08/13/json-light-support-rest-sharepoint-api-released/
Just to recap, the options are:
accept: application/json; odata=verbose
This is probably what you’re used to, and requires the heaviest payload. Using this option, you’ll get the maximum amount of information about the data coming your way, and you’ll also have to send more as well.
accept: application/json; odata=minimalmetadata
This is the middle ground. You’ll get some metdata, and you’ll also need to send some, but it’s less.
accept: application/json; odata=nometadata
This option means we won’t get any metadata and we also don’t have to send any.
accept: application/json
If you don’t specify the odata setting at all, it will default to odata=minimalmetadata.
You can use these settings both on the inbound and outbound part of your REST calls.
Content-Type: "accept: application/json; odata=minimalmetadata"
means that you are sending data that contains minimal metadata.
Likewise,
Accept: "accept: application/json; odata=verbose"
means that you want to receive data with full metadata information.
In many cases, you’ll want to use odata=verbose
as you’re debugging and switch to odata=nometadata
once you move into production. The metadata tells you a lot about the data coming and going and can be helpful as you build up your calls. If you don’t make that switch, there will be more data going down the wire, though in many cases that doesn’t matter too much. Since I learned to code back when nibbles were expensive storage, I tend to want to reduce data size as much as I can, though.
Unfortunately, I don’t think many SharePoint developers realize what all this can do for you. I hear people say all the time that REST calls are too “chatty”. In many cases, that’s simply not true; you developers are making things too chatty!
This allows you to switch from something like:
var data = { "__metadata": { "type": "SP.Data.FC_x0020_RunsListItem" }, "Title": run.RunID, "RunDate": run.RunDate, "OperatorId": run.Operator.Id, "DataIDs": dataIds.join(","), "FCData": angular.toJson(run.samples) }; var request = { method: 'POST', url: url, data: JSON.stringify(data), headers: { "Accept": "application/json; odata=verbose", "content-type": "application/json;odata=verbose", "X-RequestDigest": document.getElementById("__REQUESTDIGEST").value, "X-HTTP-Method": method, "IF-MATCH": "*" } };
to:
var data = { "Title": run.RunID, "RunDate": run.RunDate, "OperatorId": run.Operator.Id, "DataIDs": dataIds.join(","), "FCData": angular.toJson(run.samples) }; var request = { method: 'POST', url: url, data: JSON.stringify(data), headers: { "Accept": "application/json", "content-type": "application/json;odata=nometadata", "X-RequestDigest": document.getElementById("__REQUESTDIGEST").value, "X-HTTP-Method": method, "IF-MATCH": "*" } };
This is a real example from some of my code in a client project. It may not look like a huge savings, but if you are passing a lot of data either way, it can make a difference.
UPDATE on 3 May: Tip from Mikael Svenson (@mikaelsvenson) – If you’re running on premises SharePoint 2013, you may need to enable the multiple metadata formats for JSON. See:
Nibbles?!? You are old!
Each response will have a different response JSON structure, so you may also want to add
function getresponse(property) {
if (response.hasOwnProperty(property)) response = response[property];
}
response = xhr.response || xhr.statusText;
getresponse(‘value’);
getresponse(‘d’);
getresponse(‘results’);
to return a resultsset no matter what you called for.
Note, I am not using an IF ELSE structure because this code now has only one hasOwnProperty and thus minifies better (my .ajax function is 578 Bytes… try that with jQuery ;-)
Thanks very useful. I was playing around with REST in Postman and was getting wayyy too much info back
Hi , do you know why sometimes only verbose works ? I tried other option for this endpoint /_api/web/Webs?$select=Url,Title and it returns error
{
“error”: {
“code”: “-1, Microsoft.SharePoint.Client.ClientServiceException”,
“message”: {
“lang”: “en-US”,
“value”: “The HTTP header ACCEPT is missing or its value is invalid.”
}
}
}
thx
@jeffangama:
The error says “The HTTP header ACCEPT is missing or its value is invalid”, so I’d check the spelling of what you have in the headers. Typos get me more than anything!
I just tried
/_api/web/Webs?$select=Url,Title
in a browser, and it worked fine.M.
Thank you, this had been something that was tripping me up.
Why did I sometimes need to specify…
“__metadata”: {
“type”: “SP.View”
}
… and sometimes not? Why do the responses sometimes have a “type” element within a “__metadata” element, but other times have an “odata.type” element at the top level? I’d just started to notice that this varied depending on what I put in the “Accept” and “Content-Type” headers.
@Rob:
Take a look at this old post: Making Your REST Calls Simpler by Changing the Metadata Setting. That should explain why the __metadata is or isn’t required. Any inconsistencies you see in the responses are essentially Microsoft’s fault. Everything ought to be consistent, but different teams have implemented the APIs over the years.
Depending on what you’re doing and what version of SharePoint you’re using, I highly recommend using the PnPjs library to make these calls easier.
M.