Using REST in SharePoint App to perform CRUD Operations

Posted by: Mahesh Sabnis , on 9/17/2014, in Category SharePoint
Views: 40204
Abstract: The SharePoint 2013 REST interface opens the SharePoint development platform to standard Web technologies and languages. In this article we will explore how to use REST in SharePoint Apps.

SharePoint is a web application framework that enables you to develop Content-driven, Scalable and Collaborative applications. In SharePoint 2013, Microsoft has fundamentally changed how developers can create web applications using the new cloud app model.

Some Important Features about the SharePoint 2013 App

  • SharePoint App is a single package of functionality which can be deployed and activated on-site and has less overhead on a SharePoint Server Farm.
  • This package contains all the SharePoint artifacts like Lists, Libraries, etc. along with Pages, Scripts, CSS etc. that are used for an application.
  • Apps can be easily deployed on the site and can also be easily removed when they are no longer required.
  • Apps does not use any Server-Side Object Model (SSOM) in the code, hence the code does not create any unmanageable code on the server farm and does not corrupt memory.

This article is published from the DotNetCurry .NET Magazine – A Free High Quality Digital Magazine for .NET professionals published once every two months. Subscribe to this eMagazine for Free and get access to hundreds of free .NET tutorials from experts

Additional information about Apps for SharePoint can be found here: http://msdn.microsoft.com/en-us/library/office/fp179930(v=office.15).aspx

A SharePoint App can be designed using Visual Studio 2012 Ultimate with update 4 or Visual Studio 2013 Ultimate (recommended use Update 2). SharePoint Apps can be deployed on SharePoint online (http://portal.microsoftonline.com) or using on-premise infrastructure. If on-premise infrastructure is used, then the required configuration laid down by Microsoft is a must for the development and deployment of the app. The steps for configuring an environment for Apps can be found from the following link. http://technet.microsoft.com/en-us/library/fp161236(v=office.15).aspx

History of the SharePoint API Programming Model

SharePoint technology is already very popular and several professionals and enterprises have built many applications using the Object Model (OM) provided by it. Developers have been able to build Web parts and have access to the SharePoint’s Server-Side Object Model (SSOM) that allows them to call SharePoint data and perform operations programmatically. This feature has helped them to build all kinds of solutions.

In SharePoint 2010, if you had to customize or add new features to SharePoint, the only way was to reluctantly install code (which could be untrusted) directly into SharePoint's servers. Although sandbox solutions existed, the restrictions applied were stringent which forced developers to run even untrusted custom code, in full-trust mode. Some of the issues of running fully trusted code in SharePoint 2010 was it could destabilize the whole farm and it was a challenge to migrate to newer versions of SharePoint. Since the code made use of SSOM and ran as a part of SharePoint Processes, there was possibility of high memory consumption and CPU utilization. So to manage the code well, it became an overhead for developers to know about SSOM objects and dispose them appropriately to reduce memory utilization.

How does REST fit in SharePoint Programming?

 

In the earlier versions of SharePoint, SOAP based web services were provided for performing data operations, but ultimately it was only SSOM that was used to write programs with SOAP. This lead to bulky data transfers as a result of SOAP formatted XML payload. Because of this drawback (and a couple of others) of SSOM and SOAP based web services, the developers’ community was provided with a new set of APIs for developing SharePoint solutions and integrating them with various types of clients.

 

In SharePoint 2010, developers were provided with Client Side Object Model (CSOM) using which the ability of accessing SharePoint functionality was made possible in remote client applications like Silverlight.

CSOM was made available in the following flavors:

  • Managed Code (.NET)
  • Silverlight
  • ECMA Script (actually JavaScript)

The underlying protocols that the CSOM used to talk to SharePoint were XML and JSON (JavaScript Object Notation) so that other systems that could make HTTP requests could make calls to SharePoint Data. This was a major feature because code created with CSOM was running remotely. One limitation of CSOM was that it has provided API support for SharePoint Foundation like Sites, Lists and Documents.

In SharePoint 2013, a new API support has been added along with the one provided in SharePoint 2010. This provides access to its APIs in several forms, to help development of remote applications using REST/OData for .NET as well as for working with frameworks other than .NET. With this new set of APIs, if developers want to use client applications not using managed code or Silverlight, they can consider the use of REST/OData endpoints to read/write data from and to SharePoint. Since the REST interface doesn’t require any reference to assemblies, it also allows you to manage and limit the footprint of your Web applications; an important consideration especially when you are building mobile apps for Windows Phone written using HTML and JavaScript. One of the biggest advantage is that we can make use of JavaScript libraries like, jQuery, Knockout, Angular, etc to build applications, ultimately making use of the skillsets most developers are equipped with.

The APIs endpoints can be accessed using _API. This is a single endpoint for all remote APIs provided in SharePoint 2013. _API is fully REST and OData enabled. Some example url’s are as shown here:

http://HostServer/sites/MyDeveloper/_api/web/Lists

http://HostServer/sites/MyDeveloper/_api/web/Lists/getbytitle('MyList')/

Using REST in SharePoint App

In SharePoint 2013 with SharePoint Hosted Apps, we often need to access SharePoint List data for performing CRUD operations. Since SharePoint Apps are programmed using JavaScript and we have a REST API with us, it is possible to use Ajax methods to make calls to the SharePoint List.

The scenario discussed here is that the SharePoint List is available on the site collection. This list can be accessed using SharePoint App for performing CRUD operations. But there exists an isolation between List and the SharePoint App. So in this type of a scenario, our SharePoint App must have access permissions to the specific list on which operations need to perform.

The SharePoint App JavaScript code can locate the List in the site collection using the following url approaches:

var url = SPAppWebUrl + "/_api/SP.AppContextSite(@target)" +
    "/web/lists/getbytitle('" + listName + "')/items?" +
    "@target='" + SPHostUrl + "'"

In the above code, the SPAppWebUrl represents the SharePoint App URL where the App is hosted and SPHostUrl represents the URL for the Site collection from where the List is accessed. The listName is the list on which operations are to be performed.

var url = _spPageContextInfo.siteAbsoluteUrl + "/_api/web/lists/getbytitle('" + listName + "')/items"

In the above code, the _spPageContextInfo is the JavaScript or jQuery variable that provides properties used during SharePoint App development for locating the SharePoint Site collection for performing Ajax calls.

(Note: In this article we have used the second approach)

For performing operations, we will use the SharePoint 2013 Developer site with the List name ‘CategoryList’ as shown here:

category-list

For the implementation, we will use jQuery and Knockout.js. More information about jQuery and Knockout.js, can be obtained from the following links: www.jQuery.com and www.knockoutjs.com

Step 1: Open Visual Studio 2012 Ultimate with Update 4 or Visual Studio 2013 Ultimate (recommended Update 2) and create a new SharePoint App application with the name ‘SPS_REST_APP_CRUD’:

sharepoint-app-project

After clicking ‘OK’, in the ‘Specify the app for SharePoint Settings’ window, set the site name and hosting option for the app as shown here:

sharepoint-config

Step 2: From the Scripts folder of the project, open App.js and remove the already available code from it. Now add the following JavaScript which will read the parameters of the URL to get the Host Web Url and App Web Url:

'use strict';

var SPHostUrl;
var SPAppWebUrl;

// read URL parameters
function retrieveQueryStringParameter(param) {
    var params = document.URL.split("?")[1].split("&");
    var strParams = "";
    for (var i = 0; i < params.length; i = i + 1) {
        var singleParam = params[i].split("=");
        if (singleParam[0] == param) {
            return singleParam[1];
        }
    }
}


SPAppWebUrl = decodeURIComponent(retrieveQueryStringParameter("SPAppWebUrl"));
SPHostUrl = decodeURIComponent(retrieveQueryStringParameter("SPHostUrl"));

In the same JavaScript file, create a function which will define observables and functions to act as a ViewModel so that it can be used for DataBinding on the UI elements which we will be adding to Default.aspx.

//The View Model used for
//1. Defining the ListName
//2. Defining observables used for databinding with UI
//3. getCategories () => Make call to SharePoint List to Read Categories Data
//4. createCategory() => Define the Data object to be passed to SharePoint List to Add a new Record in it
//5. getCategoryById() => Retrieve a specific record from the SharePoint List based upon the Id
//6. updateCategory() => Update a specific Crecord retrived using getCategoryById() function
//7. deleteCategory() =>  Delete a specific Crecord retrived using getCategoryById() function
var crudViewModel = function () {
    var self = this;
    var listName = "CategoryList";

    self.Id = ko.observable();
    self.Title = ko.observable();
    self.CategoryName = ko.observable();

    self.Category = {
        Id: self.Id,
        Title: self.Title,
        CategoryName:self.CategoryName
    };

     

    self.Categories = ko.observableArray();
    self.error = ko.observable();

     
   //Function to Read all Categories 
  self.getCategories = function() {
        $.ajax({
            url: _spPageContextInfo.siteAbsoluteUrl + "/_api/web/lists/getbytitle('" + listName + "')/items",
            type: "GET",
            headers: { "Accept": "application/json;odata=verbose" },  
            success: function (data) {
                self.Categories(data.d.results);
            },
            error: function (data) {
                self.error("Error in processing request " + data.success);
            }
        });
    };

    //Function to Create  Category
  self.createCategory = function () {
        var itemType = "SP.Data.CategoryListListItem";
        var cat = {
            "__metadata": { "type": itemType },
            "Title": self.Title,
            "CategoryName": self.CategoryName
        };

        $.ajax({
            url: _spPageContextInfo.siteAbsoluteUrl + "/_api/web/lists/getbytitle('" + listName + "')/items",
            type: "POST",
            contentType: "application/json;odata=verbose",
            data: ko.toJSON(cat),
            headers: {
                "Accept": "application/json;odata=verbose", // return data format
                "X-RequestDigest": $("#__REQUESTDIGEST").val()
            },
            success: function (data) {
                self.error("New Category Created Successfully");
            },
            error: function (data) {
                self.error("Error in processing request " + data.status);
            }
        });
        self.getCategories();
    };

//Function to get Specific Category based upon Id
  function getCategoryById  (callback) {
      var id = self.Id();
    
     

      var url = _spPageContextInfo.siteAbsoluteUrl + "/_api/web/lists/getbytitle('" + listName + "')/items(" + id + ")";


      $.ajax({
          url: url,
          type: "GET",
          headers: { "Accept": "application/json;odata=verbose" },
          success: function (data) {
              
              callback(data);
          },
          error: function (data) {
              self.error("Error in processing request");
          }
      });

  };

    //Function to Update Category
  self.updateCategory = function () {

      getCategoryById(function (data) {
          var itemType = "SP.Data.CategoryListListItem";

          var cat = {
              "__metadata": { "type": itemType },
              "Title": self.Title,
              "CategoryName": self.CategoryName
          };

          $.ajax({
              url: data.d.__metadata.uri,
              type: "POST",
              contentType: "application/json;odata=verbose",
              data: ko.toJSON(cat),
              headers: {
                  "Accept": "application/json;odata=verbose",
                  "X-RequestDigest": $("#__REQUESTDIGEST").val(),
                  "X-HTTP-Method": "MERGE",
                  "If-Match": data.d.__metadata.etag
              },
              success: function (data) {
                  self.error("Update Success");
              },
              error: function (data) {
                  self.error("Error in processing request " + data.status + "    " + data.statusCode);
              }
          });
      });

  };

//Function to Delete Category
  self.deleteCategory = function () {
        getCategoryById(function (data) {
            alert("Procssing DELETE");
            $.ajax({
                url: data.d.__metadata.uri,
                type: "POST",
                headers: {
                    "Accept": "application/json;odata=verbose",
                    "X-RequestDigest": $("#__REQUESTDIGEST").val(),
                    "X-HTTP-Method": "DELETE",
                    "If-Match": data.d.__metadata.etag
                },
                success: function (data) {
                    self.error("DELETE Success");
                },
                error: function (data) {
                    self.error("Error in processing request " + data.status + "    " + data.statusCode + "Please try again");
                }
            });
        });
    };

    //Function to Select Category used for Update and Delete
    self.getSelectedCategory = function (cat) {
        self.Id(cat.Id);
        self.Title(cat.Title);
        self.CategoryName(cat.CategoryName);
    };

    //Function to clear all Textboxes
    self.clear = function () {
        alert("Clear");
        self.Id(0);
        self.Title("");
        self.CategoryName("");
    };

};

In the above code, the getCategories() defines ‘headers’ as "Accept": "application/json;odata=verbose". This represents the format for the return data from the call made to the SharePoint service. The function createCategory() defines the data to be saved in the list as shown here:

var itemType = "SP.Data.CategoryListListItem";
var cat = {
    "__metadata": { "type": itemType },
    "Title": self.Title,
    "CategoryName": self.CategoryName
};

The itemType variable is set to the value as SP.Data.CategoryListListItem because the name of the List is CategoryList. So keep one thing in mind that if you want to use the above logic for various SharePoint Lists, then the value for ‘itemType’ variable must be generalized. This value is then passed with ‘__metadata’. This helps to tag the structural content so that before performing write operations on the SharePoint object, the data is checked. The updateCategory() and deleteCategory() functions makes call to getCategoryById() functions to perform respective operation. The headers information to be passed for the Update is as shown here:

headers: {
  "Accept": "application/json;odata=verbose",
  "X-RequestDigest": $("#__REQUESTDIGEST").val(),
  "X-HTTP-Method": "MERGE",
  "If-Match": data.d.__metadata.etag
},

The header information sets the HTTP method to ‘Merge’ which checks the record’s availability and if the record is found, then it is updated. Similar values are also set in headers during the delete operation; the only difference is the Http Method is specified as ‘Delete’ as shown here:

headers: {
    "Accept": "application/json;odata=verbose",
    "X-RequestDigest": $("#__REQUESTDIGEST").val(),
    "X-HTTP-Method": "DELETE",
    "If-Match": data.d.__metadata.etag
},

Step 3: Open Default.aspx and add the HTML Table and other UI elements with databind expressions for observables and functions declared in ViewModel as shown here: (marked with data-bind attribute)

 



    
Id
CategoryId
CategoryName
IdCategory IdCategory Name

Step 4: Since we are performing Read/Write operations on the SharePoint List, we need to set the concerned permissions for the app. To set these permissions, double-click on the AppManifest.xml and from the Permissions tab, add the permissions as shown here:

permission-tab

Step 5: Build the App and if it is error free, then Deploy. Once the deployment is successful, the trust page will be displayed as shown here:

sp-rest-app-crud

Since we are performing operations on the CategoryList; from the ComboBox, select the CategoryList and click on the ‘Trust It’ button as seen here:

sharepoint-trust

This will bring up the credentials window. Enter Credentials and the App will be displayed with Category List data:

app-1

Add values for CategoryId and CategoryName (Id gets generated automatically) and click on the ‘Save’ button. The Record message gets displayed as seen here:

new-category

If any row from the table showing the categories is clicked, then that record gets displayed in the textboxes:

display-record

Now this record can be updated and deleted.

edit-delete-record

Similarly, you can also test the Delete functionality.

Conclusion

The SharePoint 2013 REST interface is a powerful approach that provides most functionalities that Web and Mobile app developers seek for. It makes it really simple to work with SharePoint data using client side JavaScript libraries and frameworks. This opens the SharePoint 2013 development platform to standard Web technologies and languages.

Download the entire source code from our GitHub Repository at bit.ly/dncm14-sharepointrest

Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+
Further Reading - Articles You May Like!
Author
Mahesh Sabnis is a DotNetCurry author and Microsoft MVP having over 17 years of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions). Follow him on twitter @maheshdotnet


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by macgile on Sunday, November 2, 2014 10:58 AM
Hi Mahesh Sabnis,

I tested the source code in my 2013 sharepoint online site dev and when I add an item I get the error "Error in processing request 400" and the item is not added permanently.

Can you help me?
Comment posted by MAhesh Sabnis on Wednesday, November 12, 2014 3:21 AM
Hi macgile,
Can you please check values for spPageContextInfo.siteAbsoluteUrl. It must browsable. Please check whether can you access the List Items using the same url.
Regards
Mahesh Sabnis
Comment posted by Bob Kennelly on Sunday, January 4, 2015 11:59 AM
Thanks very much Mahesh, this is really an excellent app, thank you very much!!!!
Comment posted by Test on Wednesday, February 11, 2015 3:24 AM
Test
Comment posted by sasi on Thursday, March 26, 2015 8:02 AM
what is the crud operation for share point ?

Categories

JOIN OUR COMMUNITY

POPULAR ARTICLES

FREE .NET MAGAZINES

Free DNC .NET Magazine

Tags

JQUERY COOKBOOK

jQuery CookBook