Why the SharePoint REST API is Better than SharePoint's CSOM

As a SharePoint developer, I explain why I prefer REST API over CSOM despite its downsides. Learn about its advantages & access a wide range of samples.

By Last Updated: October 22, 2013 3 minutes read

A few months ago I wrote how I prefer using the REST API in SHAREPOINT over using the CSOM. Sure there are some downsides to this (no coverage for workflow or taxonomy, no batching just to name a few). However the advantages outweigh the downsides (3rd part libraries and frameworks mostly work with REST, more standards, more samples because it isn’t SharePoint specific, etc).

One complaint I get from people is from the fact you have a bit more code to write for each call. Sure… you have to build the request each time, but that’s just an opportunity for reuse.

I’ve created two libraries I use for all my SharePoint REST calls that really cut down on constantly rewriting the same thing over and over. At the same time, this makes it a lot more readable.

The first one is used to get the SharePoint specific URLs:

The second one is for generating the calls for reads & writes. As you can see, different methods are used for different tasks:

And now, when I want to get data, the call is quite clean (the following examples are from my SharePoint 2013 App, a SharePoint Hosted App implemented as a Single Page Application (SPA)):

// get all learning paths
var query = spAppUtils.getAppODataApiUrl()
+ "/web/lists/getbytitle('Learning Paths')/Items"
+ "?$select=Id,Title,Published,Keywords1,OData__Comments"
+ "&$filter=Published eq '" + ((published) ? 1 : 0) + "'"
+ "&$orderby=Title";

// execute query
return $.ajax(oDataUtils.getRequest(query))
.then(onSuccess)
.fail(onGetLearningPathFail);

As are creates…

//create new object
var payload = buildJsonLearningItemPayload(learningItem);
endpoint = spAppUtils.getAppODataApiUrl()
+ "/web/lists/getbytitle('Learning Items')/Items";
requestData = oDataUtils.newItemRequest(endpoint, payload);

// add handlers
requestData.success = function (response) { deferred.resolve(response); };
requestData.error = function (error) { deferred.reject(error); };

// submit query
$.ajax(requestData);

and updates…

//update existing object
var payload = buildJsonLearningItemPayload(learningItem)
endpoint = learningItem._permalink();
requestData = oDataUtils.updateItemRequest(endpoint, payload, learningItem._etag());

// add handlers
requestData.success = function (response) { deferred.resolve(response); };
requestData.error = function (error) { deferred.reject(error); };

// submit query
$.ajax(requestData);

Or deletes…

//delete existing object
var endpoint = learningItem._permalink();
var requestData = oDataUtils.deleteItemRequest(endpoint);

// add handlers
requestData.success = function (response) { deferred.resolve(response); };
requestData.error = function (error) { deferred.reject(error); };

// submit query
$.ajax(requestData);

In the samples above, I use the same method for creating the object I’m going to send to the rest services in the create-update-delete operations:

/* Create a JSON object to post to the learning item */
function buildJsonLearningItemPayload(learningItem) {
  var payload = {
    __metadata: { "type": "SP.Data.LearningItemsListItem" },
    Title: learningItem.Title(),
    OData__Comments: learningItem.Description(),
    URL: {Url: learningItem.URL(),
    Description: learningItem.URL()},
    ItemType: learningItem.ItemType(),
    LearningPathId: learningItem.AssociatedLearningPath().Id()
    };

  return JSON.stringify(payload);
};

Cool huh? In reality I combine these two in my SharePoint projects. I broke them up here for readability. If I’m not working in SharePoint, I don’t need the stuff in the first script.