I ran into a strange issue today when using the SharePoint 2013 REST API for Lists with Managed Metadata columns. For a multi-select taxonomy column, the List service returns Label text as expected. But if you change that same column to single-select, suddenly an ID is returned in the Label field!
For instance, consider an
Orders list with a
Product multi-select taxonomy field. I run the following REST query to dump all the list items:
http://sharepointificate/_api/web/Lists/GetByTitle('Orders')/Items
All is good and the Product label text is returned:
Now if I just change Product to single-select and run that same query, the friendly label is gone! This
has to be a bug. Yes, YOU, Microsoft. I'm talking to you!
Luckily, there is a workaround. The Taxonomy label is correctly returned when we use a CAML query to retrieve the list items. Erik C. Jordan's answer on this
MSDN thread reveals a way to use CAML against the REST API. This guy must be some kind of SP savant, because I can find absolutely no other documentation on this method—
but it works:
/GetByTitle('Orders')/GetItems(query=@v1)?@v1={'ViewXml':'<View><Query></Query></View>'}
A couple things to note:
- GetItems is a POST operation. The query above will not work when run from your browser's address bar, which performs a GET. You need a tool like Fiddler to send a POST message to the REST endpoint. More likely, you'll be doing a jQuery ajax call like the example below.
- An X-RequestDigest message header is required for POST operations against the REST API. Its value differs between environments and apps. If this header is missing or incorrect, the server will return a 403 Forbidden error. When executing within a SharePoint-hosted or on-premise context, it should be available on the page itself, and you can grab it with $("#__REQUESTDIGEST").val(). For other contexts, you'll have to retrieve the value like this MSDN article describes.
The complete Ajax call:
$.ajax({
url: "http://sharepointificate/_api/web/Lists/GetByTitle('Orders')/GetItems(query=@v1)?@v1={'ViewXml':'<View><Query></Query></View>'}",
type: "POST",
headers: {
"Accept": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
success: function (data, textStatus, jqXHR) {
console.log(data.d.results[0].Product.Label);
},
error: function (jqXHR, textStatus, errorThrown) {
console.dir(jqXHR);
}
});