SharePoint 2013 and REST API EndPoints
SharePoint 2013 REST Interface
SharePoint 2013 provides a Representational State Transfer (REST) interface that opens the SharePoint 2013 development platform to standard Web technologies and languages. SharePoint capabilities have long been available to Web applications through the client object model, but those APIs are available only to .NET applications and languages. The extensive REST interface in SharePoint 2013 makes it possible to access most SharePoint capabilities and entities with standard Web languages such as JavaScript or PHP, and any technology stack or language that supports REST.
Because the REST interface doesn’t require referencing client assemblies, it also allows you to limit the footprint of your Web applications—an especially important consideration for mobile applications. REST has obvious benefits for mobile applications that are written for non-Microsoft platforms, such as iOS and Android devices, but it’s also a useful resource for Windows 8 app developers. A Windows 8 app written in HTML5 and JavaScript would require the REST interface for any SharePoint operations, and C# developers who are concerned about the size of their apps would also want to consider using REST. This article will demonstrate how to use this interface to incorporate the power of the SharePoint platform into your applications and perform advanced operations with SharePoint entities.
The Basics
Before it can do anything with SharePoint, your remote Web or mobile application must obtain authorized access. In SharePoint 2013 there are two general approaches to authorizing access to a SharePoint site (regardless of whether you’re using REST). The first approach involves authenticating a SharePoint user, in which case your application has the same access to SharePoint data and capabilities as the user. The different ways you can authenticate a user from a Web or mobile application are outside the scope of this article, but we’ll briefly mention two new options in SharePoint 2013 because they affect the way you construct your REST requests:- If you’re calling into SharePoint from a remotely hosted application that can’t use client-side code (HTML and JavaScript) exclusively, and there’s no firewall between SharePoint and your application, you can use OAuth 2.0 tokens with Microsoft Access Control Service (ACS) as the secure token server.
- If client-side code and the permissions of a user who’s logged in to SharePoint are sufficient, then the JavaScript cross-domain library (bit.ly/12kFwSP) is a good alternative to OAuth. The cross-domain library is also a convenient alternative to OAuth whenever you’re making remote calls through a firewall. The MSDN Library article, “Data access options for SharePoint 2013” (bit.ly/WGvt9L), describes these options in detail.
Authorization: Bearer access_token
HttpWebRequest endpointRequest =
(HttpWebRequest)HttpWebRequest.Create(
"http:// <http:///> <site url>/_api/web/lists");
endpointRequest.Method = "GET";
endpointRequest.Accept = "application/json;odata=verbose";
endpointRequest.Headers.Add("Authorization",
"Bearer " + accessToken);
HttpWebResponse endpointResponse =
(HttpWebResponse)endpointRequest.GetResponse();
var executor = new SP.RequestExecutor(appweburl);
executor.executeAsync(
{
url:
appweburl +
"/_api/SP.AppContextSite(@target)/web/lists?@target='" +
hostweburl + "'",
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: successHandler,
error: errorHandler
}
);
http://<domain>/<site url>/_api/
http://<domain>/<site url>/_api/web/lists
_api/web/lists/getByTitle('samplelist')/
Every major class of the SharePoint content object model is available, including site collection, Web sites, lists, folders, fields and list items. You can get information about users through the SP.User (bit.ly/15M4fzo), SP.UserCollection (bit.ly/16TQTnW), SP.Group (bit.ly/X55Pga) and SP.GroupCollection (bit.ly/ZnFHbG) classes. The table in Figure 1 shows examples of various endpoints for read operations.
Figure 1 Endpoints for Read Operations
URL | Returns |
_api/web/title | The title of the current site |
_api/web/lists(guid'<list id>') | A list |
_api/web/lists/getByTitle('Announcements')/fields | The columns in the Announcements list |
_api/web/lists/getByTitle('Task')/items | The items in the Task list |
_api/web/siteusers | The users in the site |
_api/web/sitegroups | The user groups in the site |
_api/web/sitegroups(3)/users | The users in group 3 |
_api/web/GetFolderByServerRelativeUrl('/Shared Documents') | The root folder of the Shared Documents library |
_api/web/GetFolderByServerRelativeUrl('/Plans')/Files('a.txt')/$value | The file a.txt from the Plans library |
accept: application/json;odata=verbose
We’ll describe later how you can use OData query operators to select, filter and order the data.
Writing to SharePoint All of the previous requests use the HTTP verb GET. When you write to SharePoint, your requests use the POST verb—though in some cases you’ll override this verb by adding an X-HTTP-Method header to the request and specifying a value of PUT, MERGE or DELETE. In general, POST is used when you’re creating an object such as a site, list or list item. MERGE is used when you’re updating certain properties of an object and you want the other properties to keep their current values. PUT is used when you want to replace an item; properties not specifically mentioned in the request are set to their default values. DELETE is used when you want to remove an item.
Every request that writes to SharePoint must include a form digest. Your code gets the digest as part of a set of information returned by the following endpoint:
_api/contextinfo
Note that if you’re working with a SharePoint-hosted app and a page that uses the default master page for SharePoint, the digest is already on the page in an element with the ID “__REQUESTDIGEST” (with two underscore characters). So, instead of calling the contextinfo endpoint, you can simply read the value with script such as this jQuery code:
var formDigestValue = $("__REQUESTDIGEST").val()
content-type: application/json;odata=verbose
Advanced Operations
A certain degree of complexity comes along with the power of the SharePoint 2013 REST interface. The interface supports operations for sorting, filtering and ordering the data that it returns. It also supports a large number of SharePoint-specific operations. These additional capabilities add features and benefits that you don’t always see in a standard REST implementation. The next sections discuss some of the most important factors you’ll encounter when working with REST and SharePoint.Filtering, Selecting and Sorting You can use OData system query options to control what data is returned and how it’s sorted. Figure 2 shows the supported options.
Figure 2 Options for Filtering and Sorting Data
Option | Purpose |
$select | Specifies which fields are included in the returned data. |
$filter | Specifies which members of a collection, such as the items in a list, are returned. |
$expand | Specifies which projected fields from a joined list are returned. |
$top | Returns only the first n items of a collection or list. |
$skip | Skips the first n items of a collection or list and returns the rest. |
$orderby | Specifies the field that’s used to sort the data before it’s returned. |
_api/web/lists/getByTitle('Books')/items?$select=Author,Title,ISBN
To get all the books by Mark Twain, use:
_api/web/lists/getByTitle('Books')/items?$filter=Author eq 'Mark Twain'
To sort the books by title in ascending order, use:
_api/web/lists/getByTitle('Books')/items?$orderby=Title asc
You can conjoin multiple options using the “&” operator. To get only the Title of the first two books by Mark Twain, use:
_api/web/lists/getByTitle(
'Books')/items?$select=Title&$filter=Author eq 'Mark Twain'&$top=2
_api/web/lists/getByTitle('Books')/items?$top=10&$skip=2
_api/web/lists/getByTitle('Books')/items?$skip=2&$top=10
_api/web/lists/getByTitle('Books')/items?$orderby=ID desc&$top=2
_api/web/lists/getByTitle(
'Books')/items?$select=Title,PublishedBy/Name&$expand=PublishedBy
Working with Files and Folders The best way to reach a document library is by taking advantage of the GetFolderByServerRelativeUrl method that’s available at /_api/web. When you add a file to a document library, you send the contents of your file in the request body, and you pass the name of the file in the URL:
http://<site url>/_api/web/GetFolderByServerRelativeUrl(
'/Shared Documents')/Files/add(url='a.txt',overwrite=true)
http://<site url>/_api/web/GetFileByServerRelativeUrl(
'/Shared Documents/a.txt')/$value
http://<site url>/_api/web/GetFileByServerRelativeUrl(
'/Shared Documents/a.txt')/CheckOut()
http://<site url>/_api/web/GetFileByServerRelativeUrl(
'/Shared Documents/a.txt')/CheckIn(comment='Comment', checkintype=0)
One final consideration is that if you’re working with code (such as JavaScript) that runs in your browser client and you want to upload a file larger than 1.5MB, REST is your only option. This sort of operation with large files (larger than 1.5MB) is available only for Internet Explorer 10 (and later) and other modern browsers of equivalent vintage. The sample in Figure 3 shows how you might upload a binary file using the cross-domain library.
Figure 3 Uploading a Binary File Using the Cross-Domain Library
function uploadFileBinary() {
var executor = new SP.RequestExecutor(appweburl);
var body = "";
for (var i = 0; i < 1000; i++) {
var ch = i % 256;
body = body + String.fromCharCode(ch);
}
var info = {
url: "_api/web/lists/getByTitle('Shared Documents')/RootFolder/Files/Add(url='a.dat', overwrite=true)",
method: "POST",
binaryStringRequestBody: true,
body: body,
success: success,
error: fail,
state: "Update"};
executor.executeAsync(info);
}
ChangeQuery objects make it possible for you to query the SharePoint change log for any updates that have been made to a SharePoint site collection, site or list. The REST interface exposes a getchanges method at each of these three locations:
- /_api/site (for site collections)
- /_api/web (for sites)
- /_api/web/lists/list(guid'<list id>') or /_api/web/lists/getByTitle('list title') (for lists)
{
'query': {
'__metadata': {
'type': 'SP.ChangeQuery'
},
'Add': 'true',
'Item': 'true'
}
}
/_api/web/lists/list(guid'<list id>')/getchanges
/_api/web/lists/getByTitle('<list title>')/getchanges
{"d":
{"results":[{
"__metadata":{
"id":"https://<site url>/_api/SP.ChangeItema7e7c6e9-2c41-47c3-aae9-2b4a63b7a087",
"uri":"https://site url/_api/SP.ChangeItem",
"type":"SP.ChangeItem"},
"ChangeToken":{"__metadata":{"type":"SP.ChangeToken"},
"StringValue":"1;3;482e418a-0900-414b-8902-02248c2e44e8;634955266749500000;5749111"},
"ChangeType":1,
"SiteId":"ce11bfbb-cf9d-4b2b-a642-8673bd48cceb",
"Time":"2013-02-03T22:17:54Z",
"ItemId":1,
"ListId":"482e418a-0900-414b-8902-02248c2e44e8",
"WebId":"a975b994-fc67-4203-a519-b160175ca967"}]
}
}
You can also use the value of the ChangeToken object when you use the getListItemChangesSinceToken method:
/_api/web/lists/list(guid'<list id>')/getListChangesSinceToken
{
'query': {
'__metadata': {
'type': 'SP.ChangeLogItemQuery'
},
'ChangeToken':'1;3;482e418a-0900-414b-8902-02248c2e44e8;634955266749500000;5749111'
}
}
- “SharePoint 2013: Using the search REST service from an app for SharePoint” (bit.ly/Mt4szN)
- “Get started developing with social features in SharePoint 2013” (bit.ly/102qIGM)
- “BCS REST API reference for SharePoint 2013” (bit.ly/10FFMMu)
Debugging
The most important piece of information you need in order to perform a REST operation is obviously the correct URL. We’ve mentioned a lot of the most important ones, and for many of the others, you can refer to the SharePoint SDK. Because the REST interface is modeled on the client object model, you can refer to the JavaScript object model reference for information about REST endpoint URLs. For example, if you want to see what URLs are available for working with list collections, you can refer to the reference documentation for the SP.ListCollection object at bit.ly/108hI1e.You can also navigate to a REST URL as a logged-in user and view the XML output of any GET request in order to see the available data at each endpoint and how it’s structured. This won’t help you with POST requests, but it can help you familiarize yourself with the different SharePoint entities and the information available at each endpoint.
It’s important that the HTTP requests you send from your code contain correctly encoded URLs. When you launch an app for SharePoint from SharePoint, you can retrieve an encoded URL from the SPHostUrl query string argument, but in other contexts you might have to encode the URL yourself.
When you’re doing more complex operations—especially when you’re performing operations that require the POST HTTP verb—you’ll need to use an HTTP tracing utility in order to debug your HTTP requests. SharePoint returns error messages whenever you make a bad request, and those messages can tell you a lot about what’s going wrong with your requests. For example, your application or user may simply not be authorized to get certain kinds of information from SharePoint. At other times, you may have constructed an invalid JSON object, or you might have assigned an invalid value to a property.
Some frameworks provide HTTP tracing utilities for you. You can use trace.axd (bit.ly/8bnst4) when you’re working with ASP.NET applications. If you’re sending requests directly from your browser, as with JavaScript, you can use Fiddler (fiddler2.com/fiddler2). We used Fiddler to generate the sample HTTP responses we included in this article.
Using REST to Talk to SharePoint in a PHP Application
As we said in our introduction, the REST interface allows you to interact with SharePoint from any of the standard languages and frameworks Web developers commonly use. In order to demonstrate this, we’ve published a sample PHP application that demonstrates how you can interact with a SharePoint site from a remote Web application written in PHP. This particular application is an app for SharePoint that’s designed to be launched from an Office 365 SharePoint site and run from a Windows Azure Web Site. This architecture simplifies some steps, such as publishing the Web site, but the PHP code in the sample can run on any architecture that supports PHP.You can view and download the sample from the code gallery page at code.msdn.microsoft.com/office/SharePoint-2013-Perform-8a78b8ef. The sample demonstrates a number of things, including how to work with files and folders with REST, how to obtain a valid OAuth access token from a PHP application, and how to use the JavaScript cross-domain library. Most important for this context, it demonstrates how to retrieve files from and upload files to a SharePoint document library using REST and PHP.
Because the application writes data to a SharePoint site, one of the first things the application needs to do (after obtaining an access token) is request the form digest from _api/contextinfo. The request passes the access token in the headers and sets up a POST request to an SSL URL. The code, shown in Figure 4, will be familiar to anyone who has worked with PHP client URL objects.
Figure 4 Requesting the Form Digest
$opts = array (
'Authorization: Bearer ' .
$accToken);
$ch = curl_init();
$url = $appweburl . '/_api/contextinfo';
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $opts);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, '');
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
$root = new SimpleXmlElement($result);
$ns = $root->getNameSpaces(TRUE);
$childrenNodes = $root->children($ns['d']);
$formValue = $childrenNodes->FormDigestValue;
$accToken = $_COOKIE["moss_access_token"];
$url = $_REQUEST["target"] .
$furl = $_FILES["file"]["tmp_name"];
$file = fopen($furl,"r");
$post_data = fread($file,filesize($furl));
fclose($file);
Figure 5 Executing the Request that Uploads the File
"/_api/web/GetFolderByServerRelativeUrl('Lists/SharedDoc')/Files/
add(url='" . $_FILES["file"]["name"] . "',overwrite=true)";
$opts = array (
'X-RequestDigest:' . $_REQUEST["digest"],
'Authorization: Bearer ' . $accToken);
// Initialize cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $opts);
// Set URL on which you want to post the Form and/or data
curl_setopt($ch, CURLOPT_URL, $url);
// Data+Files to be posted
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
// Pass TRUE or 1 if you want to wait for and catch the
// response against the request made
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// For Debug mode; shows up any error encountered during the operation
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
// Execute the request
$response = curl_exec($ch);
What Next?
Although it doesn’t have complete parity with the client object model, the SharePoint 2013 REST interface is extensive and powerful enough to provide most of what Web and mobile app developers will want to do, especially if they’re working with frameworks other than .NET. We’ve looked at many of the most important ways in which you can integrate SharePoint into your applications by using the REST interface, but there are many more possibilities.The SharePoint 2013 SDK contains a collection of resources for REST development, and you can find links to all of them on the MSDN Library page, “SharePoint 2013 REST API, endpoints and samples” (bit.ly/137q9yk). This collection will grow, and it will contain an especially wide range of samples because, as the PHP sample demonstrates, the REST interface significantly expands the world of SharePoint development.
Comments
Post a Comment