Working with the REST API in JavaScript
When you choose to use JavaScript with your app, you will find that
by using the REST API, you can write cleaner code than CSOM.
Furthermore, you will find built-in support for REST in the jQuery
library, which makes it much easier to use than CSOM. This section
details the fundamental operations necessary to work with the REST API
through JavaScript.
Example 2
shows that CSOM code rewritten by using the REST API. Comparing the two
implementations reveals that the REST version is more compact. Example 2. Welcoming the current user
$(document).ready( function () { $.getJSON(_spPageContextInfo.webServerRelativeUrl + "/_api/web/currentuser", function (data) { $("#message").text('Hello ' + data.d.Title); }); });
The RESTful URI in Example 3 is created by using the _spPageContextInfo object to retrieve a reference to the webServerRelativeUrl property. This property returns a URL, which can be concatenated with /_api to form the root of the URI. The _spPageContextInfo object is added to the ASPX pages in your app by the SPWebPartManager control, which means that you can depend on using it to form RESTful URIs in your apps.
The rewritten code makes use of the jQuery.getJSON
method to retrieve information about the current user. As the name
implies, the data returned from the call is in JSON format. JSON format
is easy to transform into a JavaScript object, which simplifies your
coding. Notice how easily the Title property for the current user is retrieved from the JSON results.
The jQuery.getJSON
method is a shorthand AJAX function that simplifies RESTful calls where
JSON is returned. For more control over the call, you can use the jQuery.ajax method. Example 3 shows the equivalent call made by using the jQuery.ajax method. Example 3. Using the jQuery.ajax method
$(document).ready( function () { $.ajax( { url: _spPageContextInfo.webServerRelativeUrl + "/_api/web/currentuser", type: "GET", headers: { "accept": "application/json;odata=verbose", }, success: function (data) { $("#message").text('Hello ' + data.d.Title); },
error: function (err) { alert(JSON.stringify(err)); } } ); });
Much like performing CSOM CRUD operations, CRUD operations in REST
should be encapsulated by using one of the JavaScript library patterns.
When you create your RESTful libraries, they can have a structure that
is very similar to the ones created for CSOM. Example 4 demonstrates a basic library structure for encapsulating RESTful CRUD operations on a contacts list. Example 4. REST library structure
"use strict";
var Wingtip = window.Wingtip || {}; Wingtip.ContactList = function () {
//private members createItem = function (lname, fname, wphone) { }, readAll = function () { }, readAllSuccess = function (data) { }, updateItem = function (id, lname, fname, wphone) { }, removeItem = function (id) { }
//public interface return { createContact: createItem, updateContact: updateItem, deleteContact: removeItem }
}();
$(document).ready(function () { Wingtip.ContactList.createContact("Cox", "Brian", "555-555-5555"); alert("Contact Created!"); Wingtip.ContactList.updateContact(1, "Cox", "Brian", "111-111-1111"); alert("Contact Updated!"); Wingtip.ContactList.deleteContact(1); alert("Contact Deleted!"); });
The primary difference between this REST
library and the CSOM library is that no additional variable is required
to reference objects between round trips to the server. Of course, the
implementation details will be drastically different.
Creating new items is done by constructing a URI that refers to the collection to which the new items are to be added and using the POST
verb to send an object containing the data for the new item. Whenever a
RESTful operation changes a SharePoint resource, the request must
include a form digest. The form digest is a security validation that
guarantees the app page has not changed since it was delivered from the
server. The easiest way to obtain the form digest is simply to read it
from the form digest control on the app page. Example 5 shows how to create a new item in a list by using this technique. Example 5. Creating new items in a list
createItem = function (lname, fname, wphone) { $.ajax({ url: _spPageContextInfo.webServerRelativeUrl + "/_api/web/lists/getByTitle('Contacts')/items", type: "POST", data: JSON.stringify( { '__metadata': { 'type': 'SP.Data.ContactsListItem' }, 'Title': lname, 'FirstName': fname, 'WorkPhone': wphone }), headers: { "accept": "application/json;odata=verbose", "X-RequestDigest": $("#__REQUESTDIGEST").val() }, success: function () { readAll();; }, error: function (err) { alert(JSON.stringify(err)); } }); }
Along with the form digest, the create operation must also include the type
metadata for the item that is being created. The type metadata is
unique to the list and can be discovered by examining the metadata
returned from a read operation. For list items, the type metadata
generally follows the pattern SP.Data, concatenated with the name of the list, concatenated with ListItem. In Example 6, the type metadata is SP.Data.ContactsListItem.
Reading items is a straightforward operation that uses a RESTful URI to request the items. This URI is called by using an HTTP GET
verb. In the sample library, all successful calls to create, update, or
delete an item result in redrawing the list in an HTML table. Example 6 shows how to retrieve the list items and render a simple HTML table to display them. Example 6. Reading items and presenting them in an HTML table
readAll = function () { $.ajax( { url: _spPageContextInfo.webServerRelativeUrl + "/_api/web/lists/getByTitle('Contacts')/items/" + "?$select=Id,FirstName,Title,WorkPhone" + "&$orderby=Title,FirstName", type: "GET", headers: { "accept": "application/json;odata=verbose", }, success: function (data) { readAllSuccess(data); }, error: function (err) { alert(JSON.stringify(err)); } } ); },
readAllSuccess = function (data) { var html = []; html.push("<table><thead><tr><th>ID</th><th>First Name</th>" + "<th>Last Name</th><th>Title</th></tr></thead>");
var results = data.d.results;
for(var i=0; i<results.length; i++) { html.push("<tr><td>"); html.push(results[i].ID); html.push("</td><td>"); html.push(results[i].FirstName); html.push("</td><td>"); html.push(results[i].Title); html.push("</td><td>"); html.push(results[i].WorkPhone); html.push("</td></tr>"); } html.push("</table>"); $('#displayDiv').html(html.join('')); }
Updating items is
accomplished by creating a RESTful URI that refers to the item that
will be updated. Just like item creation, item updating also requires
the request to include a form digest. The URI is then invoked by using a PUT, PATCH, or MERGE verb. When a PUT operation is used, you must specify all writable properties in the request. When a PATCH or MERGE operation is used, you can specify only the properties you want to change. Although MERGE and PATCH accomplish the same task, the PATCH operation is considered more standard. Example 7 shows how to update a list item by using the PATCH operation. Example 7. Updating items
updateItem = function (id, lname, fname, wphone) { $.ajax( { url: _spPageContextInfo.webServerRelativeUrl + "/_api/web/lists/getByTitle('Contacts')/getItemByStringId ('" + id + "')", type: "POST", contentType: "application/json;odata=verbose", data: JSON.stringify( { '__metadata': { 'type': 'SP.Data.ContactsListItem' }, 'Title': lname, 'FirstName': fname, 'WorkPhone': wphone }), headers: { "accept": "application/json;odata=verbose", "X-RequestDigest": $("#__REQUESTDIGEST").val(), "IF-MATCH": "*", "X-Http-Method": "PATCH" }, success: function (data) { readAll(); }, error: function (err) { alert(JSON.stringify(err)); } } ); }
When performing updates on list items, you can utilize ETags
for concurrency control. ETags are version numbers assigned at the
list-item level. This number determines whether the list item was
altered by another process since your code last read the data. You can
find the ETag for a list item by reading it from the metadata. Example 6 could be updated to display ETag values by reading them with the following code:
results[i].__metadata.etag
ETag values are sent during an update operation via the IF-MATCH
header. If the ETag sent in the update process is different from the
ETag currently assigned to the list item, the update will fail. If you
want to force an update regardless of ETag values, you can pass IF-MATCH:*, which is the approach taken in Example 7.
Deleting an item is accomplished by first constructing a URI that references the target item to delete. The URI is invoked by using an HTTP DELETE verb. The delete operation must provide a form digest and an ETag value. Example 8 shows the implementation of a delete operation. Example 8. Deleting items
removeItem = function (id) { $.ajax( { url: _spPageContextInfo.webServerRelativeUrl + "/_api/web/lists/getByTitle('Contacts')/getItemByStringId ('" + id + "')", type: "DELETE", headers: { "accept": "application/json;odata=verbose", "X-RequestDigest": $("#__REQUESTDIGEST").val(), "IF-MATCH": "*" }, success: function (data) { readAll(); }, error: function (err) { alert(JSON.stringify(err)); } } ); }
|