Danny Jessee

Access and Manipulate Data in Your CloudShare SharePoint 2013 Farm from Anywhere with CSOM, REST and OData

December 16th, 2012 | Author: | Filed under: CloudShare, Dev / Test, SharePoint | Tags: , , , , ,


SharePoint 2010 introduced the client-side object model (CSOM) to allow developers to write applications which interact with SharePoint from client-side code. In SharePoint 2013, Microsoft steps things up a notch by allowing developers to use Representational State Transfer (REST) in conjunction with the Open Data (OData) protocol to perform Create/Read/Update/Delete (CRUD) operations against SharePoint sites and lists for nearly every API in the CSOM. Through the magic of CloudShare web access, we can leverage the CSOM along with REST and OData to interact with our SharePoint 2013 environments from literally anywhere, using any type of client! All code samples in this blog post will be run from my local workstation over 1,000 miles away from my SharePoint 2013 server running in the CloudShare datacenter!

For this post, I have set up a CloudShare environment that includes the SharePoint Server 2013 RTM machine. I have also set up the Vanity URL http://dannyjessee.cld.sr for external web access to the machine. (If you haven’t already, I highly recommend that you set up a Vanity URL for your environment, too!) I then added my Vanity URL as an Alternate Access Mapping (AAM) for my SharePoint 2013 web application:

01 - SharePoint 2013 Edit public zone URLs

Using the CSOM to Add a SharePoint List with Items

The CSOM is still the mechanism of choice for interacting with SharePoint 2013 from remote .NET clients. If you are going to develop applications that interact with SharePoint 2013 from a machine that is not running SharePoint 2013, you will need to download and install the SharePoint Server 2013 Client Components SDK. This package contains the necessary DLLs to reference the CSOM (Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.Runtime.dll) and run your application. Juan Carlos provides further information about what’s new in the CSOM for SharePoint 2013 in his blog post here.

In Visual Studio 2012, I created a new console application and added references to the two DLLs necessary to leverage the CSOM that I mentioned above. I also added a using directive for Microsoft.SharePoint.Client. I wrote the following code to add a new list to my site using the Contacts list template:

// Use your CloudShare web access/Vanity URL here
string siteUrl = "http://dannyjessee.cld.sr";

ClientContext context = new ClientContext(siteUrl);
context.AuthenticationMode = ClientAuthenticationMode.Default;
// Obtain these values from your environment's home page
context.Credentials = new NetworkCredential("username", "password", "domain");

Web web = context.Web;
context.Load(web);
context.ExecuteQuery();

ListCreationInformation creationInfo = new ListCreationInformation();
creationInfo.Title = "MySpecialContactsList";
creationInfo.TemplateType = (int)ListTemplateType.Contacts;
List list = web.Lists.Add(creationInfo);
list.Description = "My Special Contacts List Description";
list.Update();

context.ExecuteQuery();

ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();
ListItem newItem = list.AddItem(itemCreateInfo);
newItem["FirstName"] = "Danny";
newItem["Title"] = "Jessee";    // Mapped to "Last Name" field
newItem.Update();

itemCreateInfo = new ListItemCreationInformation();
newItem = list.AddItem(itemCreateInfo);
newItem["FirstName"] = "John";
newItem["Title"] = "Doe";       // Mapped to "Last Name" field
newItem.Update();

context.ExecuteQuery();

Executing this code (with the appropriate credentials specified) will add the list MySpecialContactsList to my site with two items added to the list based on the values I provided:

02 - SharePoint 2013 contact list

A SharePoint REST and OData Primer

SharePoint 2013’s REST service provides access to the capabilities available through the CSOM. It enables developers to perform CRUD operations against data stored in SharePoint using the OData protocol. Nearly all CSOM APIs have a corresponding REST endpoint. JavaScript and non-.NET clients benefit the most from leveraging SharePoint 2013’s REST/OData endpoints.

In SharePoint 2013, the alias /_api has been added as shorthand for /_vti_bin/client.svc. With that in mind, a RESTful call to get information about the root SPWeb of my SharePoint 2013 web application can be made to the URL http://dannyjessee.cld.sr/_api/web. Entering this URL in the browser (and providing credentials) produces the following output:

03 - Access and Manipulate Data in Your CloudShare SharePoint 2013 Farm from Anywhere with CSOM, REST, and OData

To retrieve a specific piece of information (in this case, the Title property of the SPWeb), we use the OData $select operator and make a request to the URL http://dannyjessee.cld.sr/_api/web/?$select=Title, which reveals the “Incredibly Awesome” name I have given my site:

04 - Access and Manipulate Data in Your CloudShare SharePoint 2013 Farm from Anywhere with CSOM, REST, and OData

This is all very interesting, and while it is helpful to be able to use a web browser to test making GET requests to SharePoint 2013’s REST/OData endpoints. However, the true power in this approach lies in the ability to perform CRUD operations from external clients without running any custom code on the SharePoint server. In the next section, I will demonstrate how to perform these operations in a .NET client.

Creating, Updating, and Deleting list items using SharePoint’s REST Service

The code below makes HTTP requests to SharePoint’s REST service endpoints to add a new list item, update an existing list item, and delete a list item:

// Use your CloudShare web access/Vanity URL here
string siteUrl = "http://dannyjessee.cld.sr";
// 1. Add a new item to the list
Uri uri = new Uri(siteUrl + "_api/web/lists/GetByTitle('MySpecialContactsList')/Items");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.Credentials = new NetworkCredential("username", "password", "domain");
request.Accept = "application/json;odata=verbose";
request.ContentType = "application/json;odata=verbose";
request.Headers["X-RequestDigest"] = GetFormDigest();
string body = "{'__metadata':{'type':'SP.Data.MySpecialContactsListListItem'},'Title':'Jones','FirstName':'Adam'}";
request.ContentLength = body.Length;
StreamWriter writer = new StreamWriter(request.GetRequestStream());
writer.Write(body);
writer.Flush();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// 2. Update an existing item in the list
uri = new Uri(siteUrl + "_api/web/lists/GetByTitle('MySpecialContactsList')/Items(1)");
request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.Credentials = new NetworkCredential("username", "password", "domain");
request.Accept = "application/json;odata=verbose";
request.ContentType = "application/json;odata=verbose";
request.Headers["X-HTTP-Method"] = "MERGE";
request.Headers["If-Match"] = "*";
request.Headers["X-RequestDigest"] = GetFormDigest();
body = "{'__metadata':{'type':'SP.Data.MySpecialContactsListListItem'},'Title':'Jessee, Jr.'}";
request.ContentLength = body.Length;
writer = new StreamWriter(request.GetRequestStream());
writer.Write(body);
writer.Flush();
response = (HttpWebResponse)request.GetResponse();
// 3. Delete an item from the list
uri = new Uri(siteUrl + "_api/web/lists/GetByTitle('MySpecialContactsList')/Items(2)");
request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.Credentials = new NetworkCredential("username", "password", "domain");
request.Accept = "application/json;odata=verbose";
request.ContentType = "application/json;odata=verbose";
request.Headers["X-HTTP-Method"] = "DELETE";
request.Headers["If-Match"] = "*";
request.Headers["X-RequestDigest"] = GetFormDigest();
request.ContentLength = 0;
response = (HttpWebResponse)request.GetResponse();

Any code that updates SharePoint via an HTTP POST requires a value to be specified for the X-RequestDigest HTTP header. For code running outside of SharePoint, this the value must be retrieved by making a separate HTTP POST request to the _api/contextinfo endpoint. To accomplish this, I made use of the following method (courtesy of Ted Pattison’s post here):

string GetFormDigest()
{
    // To get the form digest for external calls, need to make a POST request to
    // http://siteUrl/_api/contextinfo
    Uri uri = new Uri(siteUrl + "_api/contextinfo");
    HttpWebRequest requestPost = (HttpWebRequest)WebRequest.Create(uri);
    requestPost.Credentials = new NetworkCredential("username", "password", "domain");
    requestPost.Method = "POST";
    requestPost.ContentLength = 0;
    HttpWebResponse responsePost = (HttpWebResponse)requestPost.GetResponse();
    XDocument doc = XDocument.Load(responsePost.GetResponseStream());
    XNamespace ns_dataservices = "http://schemas.microsoft.com/ado/2007/08/dataservices";
    return doc.Descendants(ns_dataservices + "FormDigestValue").First().Value;
}

Executing this code (again, with the appropriate credentials specified) will add an entry for Adam Jones, update my last name to “Jessee, Jr.”, and delete the entry for John Doe:

 05 - Access and Manipulate Data in Your CloudShare SharePoint 2013 Farm from Anywhere with CSOM, REST, and OData

Conclusion

Microsoft has made significant investments in enhancing and extending the CSOM, along with SharePoint’s REST/OData endpoints, to provide developers with the richness and flexibility that was previously only available through the server-side object model. These enhancements enable developers to take advantage of the new app model for SharePoint 2013 as well as develop feature-rich client and web-based applications whose code runs exclusively in the cloud (or on any server external to SharePoint). This improves the overall stability of the SharePoint platform and paves the way for less troublesome upgrades down the road.

About the author:
Danny Jessee is a senior software developer for Fulcrum IT Services, a northern-Virginia based professional services firm dedicated to helping government and industry leaders address their challenges. He has specialized in development of custom SharePoint solutions since 2004. He has supported development efforts for dozens of SharePoint deployments, many for DoD customers in locked-down secure environments. He has also developed solutions for SharePoint and ASP.NET in support of military, government, and internal corporate customers. He holds an MCPD certification in SharePoint 2010 Application Development and an MCTS in SharePoint 2010 Configuration. In his spare time, he enjoys running, meteorology, and cheering for his local sports teams. Contact info: Blog: http://dannyjessee.com/blog Twitter: @dannyjessee LinkedIn: http://www.linkedin.com/in/dannyjessee Email: djessee@sharepointexperts.org