How To: Modify SharePoint 2013 Objects Using REST Calls

In the previous article we saw how to get data from SharePoint into a console application. In this article we will see how to post data into SharePoint using a console application. Basically the idea is that, without referencing a SharePoint library, you can read and write data into SharePoint if the user whose credentials are passed has those rights on SharePoint. When getting data you use the GET verb and when writing data you use the POST verb. In some cases this POST verb can be overridden 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 a SharePoint object, such as a site, folder, file, list or list item. MERGE is used when you're editing certain properties of a SharePoint object and you want the other properties to keep their current values. PUT is used when you want to replace a SharePoint object. DELETE is used when you want to delete a SharePoint object.

In this example, let us consider that we want to create a new folder in a Shared documents library in a team site. To get a list of all folders you can type "<site_url>/_api/web/folders" in the browser and you will see XML that will have an id of each folder in that site. For example "<<Site URL>>/sites/ts/_api/web/folders" gives me data as shown in the screen below.

Share1

Let's create a new folder called "Folder Created From Code". The important elements are the method types (X-Http-Method) and setting of headers. Let's see the details on the headers.

Every request that writes to SharePoint must include a form digest. You can retrieve the form digest value by making a POST request with an empty body to the "http://site url/_api/contextinfo" and extracting the value of the FormDigestValue. For example: the following screenshot shows the FormDigestValue that is returned in my case.

Share2

To retrieve the form digest, simple string operations are used as shown below:

// Get the FormDigest Value

var startTag = "FormDigestValue";

var endTag = "LibraryVersion";

var startTagIndex = results.IndexOf(startTag)+1;

var endTagIndex = results.IndexOf(endTag, startTagIndex);

string newFormDigest = null;

if ((startTagIndex >= 0) && (endTagIndex > startTagIndex))

{

        newFormDigest = results.Substring(startTagIndex + startTag.Length+2, endTagIndex - startTagIndex - startTag.Length-5);

}

In all subsequent POST requests, you add an X-Request­Digest header with the digest as its value as shown below.

String digestRequest = "<<Site URL>>/sites/ts/_api/Web/folders";

HttpWebRequest spNewRequest = (HttpWebRequest)HttpWebRequest.Create(digestRequest);

CredentialCache credNewCache = new CredentialCache();

credNewCache.Add(new Uri(digestRequest), "NTLM", CredentialCache.DefaultNetworkCredentials);

spNewRequest.Credentials = credNewCache;

spNewRequest.Method = "POST";

spNewRequest.Accept = "application/json;odata=verbose";

spNewRequest.ContentType = "application/json;odata=verbose";     

spNewRequest.Headers.Add("X-RequestDigest", newFormDigest);

Content Length is another important header that needs to be set. If not set then the error is thrown as shown in the screen below.

Share3
 

string listPostBody = "{'__metadata':{'type':'SP.Folder'}, 'ServerRelativeUrl':'/sites/ts/Shared Documents/Folder Created From Code'}";

// For Content Length

byte[] postByte = Encoding.UTF8.GetBytes(listPostBody);

spNewRequest.ContentLength = postByte.Length;

Stream postStreamBody = spNewRequest.GetRequestStream();

postStreamBody.Write(postByte, 0, postByte.Length);

postStreamBody.Close();

The complete code is as below. Please note that this is only sample code without adding verifications and exceptions. Please do not use in production as-is; only for PoC purposes. Replace "<<Site URL>>" with your site URL.

static void Main(string[] args)

{

      // 1st request to get the context information

      string formdigestRequest = "<<Site URL>>/sites/ts/_api/contextinfo";

      CredentialCache credCache = new CredentialCache();

      credCache.Add(new Uri(formdigestRequest), "NTLM", CredentialCache.DefaultNetworkCredentials);

      HttpWebRequest spRequest = (HttpWebRequest)HttpWebRequest.Create(formdigestRequest);

      spRequest.Credentials = credCache;

      spRequest.Method = "POST";

      spRequest.Accept = "application/json;odata=verbose";

      spRequest.ContentLength = 0;

      Stream postStream;

      HttpWebResponse endpointResponse = (HttpWebResponse)spRequest.GetResponse();

      string results = GetHTTPResponse(endpointResponse, out postStream, out results);

 

      // Get the FormDigest Value

      var startTag = "FormDigestValue";

      var endTag = "LibraryVersion";

      var startTagIndex = results.IndexOf(startTag)+1;

      var endTagIndex = results.IndexOf(endTag, startTagIndex);

      string newFormDigest = null;

      if ((startTagIndex >= 0) && (endTagIndex > startTagIndex))

      {

          newFormDigest = results.Substring(startTagIndex + startTag.Length+2, endTagIndex - startTagIndex - startTag.Length-5);

      }

 

     String digestRequest = "<<Site URL>>/sites/ts/_api/Web/folders";

         

    HttpWebRequest spNewRequest = (HttpWebRequest)HttpWebRequest.Create(digestRequest);

    CredentialCache credNewCache = new CredentialCache();

    credNewCache.Add(new Uri(digestRequest), "NTLM", CredentialCache.DefaultNetworkCredentials);

    spNewRequest.Credentials = credNewCache;

    spNewRequest.Method = "POST";

    spNewRequest.Accept = "application/json;odata=verbose";

    spNewRequest.ContentType = "application/json;odata=verbose";     

    spNewRequest.Headers.Add("X-RequestDigest", newFormDigest); 

     string listPostBody = "{'__metadata':{'type':'SP.Folder'}, 'ServerRelativeUrl':'/sites/ts/Shared Documents/Folder Created From Code'}";

           

     // For Content Length

     byte[] postByte = Encoding.UTF8.GetBytes(listPostBody);

     spNewRequest.ContentLength = postByte.Length;

     Stream postStreamBody = spNewRequest.GetRequestStream();

     postStreamBody.Write(postByte, 0, postByte.Length);

     postStreamBody.Close();

     HttpWebResponse webResponse = (HttpWebResponse)spNewRequest.GetResponse();         

     results = GetHTTPResponse(webResponse, out postStream, out results);                 

} 

private static String GetHTTPResponse(HttpWebResponse endpointResponse, out Stream postStream, out string results)

{          

     postStream = endpointResponse.GetResponseStream();

     StreamReader postReader = new StreamReader(postStream); 

     results = postReader.ReadToEnd();

 

     postReader.Close();

     postStream.Close();

     return results;  

}

You will see results, a new folder added, under the Shared Documents folder as below.

Share4

In the next article, we will see how to edit and delete SharePoint objects and items from applications without referencing SharePoint libraries.