Sunday, March 29, 2015

SharePoint 2013 List CRUD operation using Angular and REST API

This article explains how to perform the CRUD operation on a SharePoint List using Angular JavaScript and the REST API.

Create an empty SharePoint 2013 solution, In that add the module of Pages, JS & CSS.

In pages module add new item, Test.aspx.
In JS module, add new Javascript file with name Controller.js , CommonServices.js & SharePointListModule.js
Other Javascripts needs to add:
1. angular.min.js

Project structure will look something like below:

In SharePointListModule.js will create a App of angular, Paste the below code.

 //App creation  
 var app = angular.module("SharePointAngApp", [])  

For doing a CRUD operation with SharePoint List, will create an Angular Service to make a SharePoint REST API calls,

 app.service('testService', ['$http', '$q', function ($http, $q) {//common services}]);

This testService having dependency of $http & $q
Information related to $http & $q$http ,$q

Following code showing how to get, add, delete & update tasks from specified SharePoint list,

 //Common service for SharePoint CRUD operations  
 app.service('testService', ['$http', '$q', function ($http, $q) {  
   var formDigest = $('#__REQUESTDIGEST').val();  
   //Define the http headers  
   $http.defaults.headers.common.Accept = "application/json;odata=verbose";  
   $['Content-Type'] = 'application/json;odata=verbose';  
   $['X-Requested-With'] = 'XMLHttpRequest';  
   $['If-Match'] = "*";  
   $['X-RequestDigest'] = formDigest;  
   //Get the tasks  
   this.getTasks = function (listTitle) {  
     var dfd = $q.defer();  
     $['X-HTTP-Method'] = ""  
     var query = "?$select=Title,Status,Priority,ID,Body";  
     var restUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('" + listTitle + "')/items" + query;  
     $http.get(restUrl).success(function (data) {  
     }).error(function (data) {  
       dfd.reject("error getting tasks");  
     return dfd.promise;  
   //Create a task , for now static text, we can pass input fields to add apropriate value   
   this.addTask = function (listTitle) {  
     var dfd = $q.defer();  
     $['X-HTTP-Method'] = "";  
     var restUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('" + listTitle + "')/items";  
     $, {  
       __metadata: {  
         type: "SP.List"  
       Title: "New Tasks"  
     }).success(function (data) {  
       //resolve the new data  
     }).error(function (data) {  
       dfd.reject("failed to add task");  
     return dfd.promise;  
   //Update a task  
   this.updateTask = function (listTitle, task) {  
     var dfd = $q.defer();  
     $['X-HTTP-Method'] = "MERGE";  
     var restUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('" + listTitle + "')/items(" + task.ID + ")";  
     $, {  
       __metadata: {  
         type: "SP.List"  
       Title: task.Title  
     }).success(function (data) {  
       //resolve something  
     }).error(function (data) {  
       dfd.reject("error updating task");  
     return dfd.promise;  
   //Delete a task  
   this.deleteTask = function (listTitle, task) {  
     var dfd = $q.defer();  
     $['X-HTTP-Method'] = "DELETE";  
     var restUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('" + listTitle + "')/items(" + task.ID + ")";  
       .success(function (data) {  
         //resolve something  
       }).error(function (data) {  
         dfd.reject("error deleting task");  
     return dfd.promise;  

Now, its time to consume all these services by creating an angular controller.
 app.controller('spTasksController', function ($scope, $http, testService) {  
 //functions to consume the service methods});  

Full code to consume the above service methods is below, paste it in Controller.js
 //Controller to featch data from Tasks list  
 app.controller('spTasksController', function ($scope, $http, testService) {  
   $scope.editing = false;  
   //example populating tasks  
   testService.getTasks("Workflow Tasks").then(function (result) {  
     $scope.tasks = result;  
   //example to add task  
   $scope.addTask = function (listName) {  
     testService.addTask(listName).then(function (result) {  
       //update the scope with new task created  
       $scope.task = {};  
   // example to update task  
   $scope.updateTask = function (listName, item) {  
     testService.updateTask(listName, item).then(function (result) {  
       $scope.editing = $scope.tasks.indexOf(item);  
   $scope.editItem = function (index) {  
     $scope.editing = $scope.tasks.indexOf(index);  
   $scope.saveField = function (index) {  
     if ($scope.editing !== false) {  
       $scope.editing = false;  
   // example to delete task  
   $scope.deleteTask = function (listName, item,index) {  
     testService.deleteTask(listName, item).then(function (result) {  
       $scope.tasks.splice(index, 1);  

Now, its time to bind the view. add the below piece of code in test.aspx
 <%@ Page Language="C#" MasterPageFile="~masterurl/default.master" Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage,Microsoft.SharePoint,Version=,Culture=neutral,PublicKeyToken=71e9bce111e9429c" meta:progid="SharePoint.WebPartPage.Document" meta:webpartpageexpansion="full" %>  
 <%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>  
 <%@ Register TagPrefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>  
 <%@ Import Namespace="Microsoft.SharePoint" %>  
 <%@ Assembly Name="Microsoft.Web.CommandUI, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>  
 <%@ Register TagPrefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>  
 <asp:Content ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">  
   <SharePoint:EncodedLiteral runat="server" Text="<%$Resources:wss,multipages_homelink_text%>" EncodeMethod="HtmlEncode" />  
      <SharePoint:ProjectProperty Property="Title" runat="server" />  
 <asp:Content ContentPlaceHolderID="PlaceHolderPageImage" runat="server">  
   <img src="/_layouts/15/images/blank.gif?rev=23" width='1' height='1' alt="" />  
 <asp:Content ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server">  
   <label class="ms-hidden">  
     <SharePoint:ProjectProperty Property="Title" runat="server" />  
 <asp:Content ContentPlaceHolderID="PlaceHolderTitleAreaClass" runat="server">  
   <SharePoint:UIVersionedContent runat="server" UIVersion="<=3">  
           <style type="text/css">  
   , .ms-pagetitleareaframe {  
               height: 10px;  
               height: 100%;  
             .ms-pagetitleareaframe table {  
               background: none;  
               height: 10px;  
             .ms-viewheadertr ms-vhltr {  
               background: rgb(246,248,249); /* Old browsers */  
               /* IE9 SVG, needs conditional override of 'filter' to 'none' */  
               background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2Y2ZjhmOSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iI2U1ZWJlZSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjUxJSIgc3RvcC1jb2xvcj0iI2Q3ZGVlMyIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmNWY3ZjkiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);  
               background: -moz-linear-gradient(top, rgba(246,248,249,1) 0%, rgba(229,235,238,1) 50%, rgba(215,222,227,1) 51%, rgba(245,247,249,1) 100%); /* FF3.6+ */  
               background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(246,248,249,1)), color-stop(50%,rgba(229,235,238,1)), color-stop(51%,rgba(215,222,227,1)), color-stop(100%,rgba(245,247,249,1))); /* Chrome,Safari4+ */  
               background: -webkit-linear-gradient(top, rgba(246,248,249,1) 0%,rgba(229,235,238,1) 50%,rgba(215,222,227,1) 51%,rgba(245,247,249,1) 100%); /* Chrome10+,Safari5.1+ */  
               background: -o-linear-gradient(top, rgba(246,248,249,1) 0%,rgba(229,235,238,1) 50%,rgba(215,222,227,1) 51%,rgba(245,247,249,1) 100%); /* Opera 11.10+ */  
               background: -ms-linear-gradient(top, rgba(246,248,249,1) 0%,rgba(229,235,238,1) 50%,rgba(215,222,227,1) 51%,rgba(245,247,249,1) 100%); /* IE10+ */  
               background: linear-gradient(to bottom, rgba(246,248,249,1) 0%,rgba(229,235,238,1) 50%,rgba(215,222,227,1) 51%,rgba(245,247,249,1) 100%); /* W3C */  
               filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f6f8f9', endColorstr='#f5f7f9',GradientType=0 ); /* IE6-8 */  
             .ms-vh2 {  
               font-size: 13px;  
               font-weight: 500;  
           </style> <!--[if gte IE 9]>  
  <style type="text/css">  
   .gradient {  
     filter: none;  
  </style> <![endif]-->  
 <asp:Content ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">  
   <meta name="CollaborationServer" content="SharePoint Team Web Site" />  
   <SharePoint:StyleBlock runat="server">  
     .s4-nothome {  
   <script type="text/javascript" src="../JS/jquery.min.js">//<![CDATA[//]]></script>  
   <script type="text/javascript" src="../JS/angular.min.js"></script>  
   <script type="text/javascript" src="../JS/SharePointListModule.js"></script>  
   <script type="text/javascript" src="../JS/Controllers.js"></script>  
   <script type="text/javascript" src="../JS/Common.Services.js"></script>  
 <asp:Content ContentPlaceHolderID="PlaceHolderSearchArea" runat="server">  
   <SharePoint:DelegateControl runat="server"  
     ControlId="SmallSearchInputBox" />  
 <asp:Content ContentPlaceHolderID="PlaceHolderLeftActions" runat="server" />  
 <asp:Content ContentPlaceHolderID="PlaceHolderLeftNavBar" runat="server">  
   <div class="page">  
     <div class="row">  
       <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">  
         <div class="navHolder" id="fisCustomNav">  
           <ul class="nav-site" id="fisNavroot">  
           <ul class="nav-device-main">  
 <asp:Content ContentPlaceHolderID="PlaceHolderPageDescription" runat="server">  
 <asp:Content ContentPlaceHolderID="PlaceHolderBodyAreaClass" runat="server">  
   <SharePoint:StyleBlock runat="server">  
     .ms-bodyareaframe {  
      padding: 0px;  
 <asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server">  
   <form class="form-horizontal" name="taskForm" novalidate>  
     <div class="page" ng-app="SharePointAngApp">  
       <div class="row">  
         <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 replacement-btn-list">  
           <h3 class="text-bold text-color-dark ">List of Tasks:</h3>  
       <div class="row">  
         <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">  
           <div class="table-responsive replacement-list" ng-controller="spTasksController">  
             <table class="table">  
                 <tr ng-repeat="task in tasks">  
                   <td><span ng-hide="editMode">{{task.Title}}</span><input type="text" ng-show="editMode" ng-model="task.Title" /></td>  
                     <input type="button" ng-hide="editMode" ng-click="editMode = true; editItem(task) " value="Edit" /></span>  
                       <input type="button" ng-show="editMode" ng-click="editMode = false; updateTask('Workflow Tasks',task)" value="Save"></span></td>  
                       <input type="button" ng-click="deleteTask('Workflow Tasks',task,$index)" value="Delete" /></div>  
                     <input type="button" ng-click="addTask('Workflow Tasks')" value="Add" /></td>  

If you noticed in parent div i have added :  <div class="page" ng-app="SharePointAngApp">
and in child div added ng-controller

  <div class="table-responsive replacement-list" ng-controller="spTasksController">

Once we add the controller, we can access all the scope variables in child elements.

Output will looks like below:

Hope this will help you to build SharePoint applications using Angualr.
Happy learning!

Thursday, February 12, 2015

“Response no longer required” error in nintex workflow

Error: “Response no longer required”

With Nintex , requirement was to create a workflow which passes through multiple approval process.
Workflow having Felxi tasks with customized task forms.
After publishing everything works well in development environment.
Time was to deploy the workflow at test environment, deployed workflow with manual import/export published it no error reported, its published successfully.

When first approval task starts, it started giving email notification something like below:

"Response no longer required"
A task regarding this item no longer requires your response:
Click here to view the workflow status

First was not sure, from where this notification coming up from workflow steps, as I haven't set any message like this in workflow, No error reported in workflow tasks, or in workflow history.
Invested almost a whole day to find the exact cause.
Finally found in flexi task configuration window under "Not require Notification"

Now I tried to find in Nintex community regrading what exactly "Not require Notification" is doing.

Not Require Notification will get sent in following scenario:

Sent when the user no longer needs to respond to the task. This can occur when:
•A task is assigned to multiple users but only one is required to respond.
•The workflow is terminated prior to the task being processed.
•An error occurs in the workflow at run time. 

Source :

At last, I got some hint from last point "
An error occurs in the workflow at run time" some run time error, my search headed towards what could be the error, created sample one step workflow with flexi task which ran well on test environment.
Means no configuration/installation issue of Nintex. only difference was customized task form.
Finally culprit found, its a customized task forms.

We need to manually import and export every flexi task's customized task forms to make it up and running.
After importing all the customized task form manually this "“Response no longer required” error is resolved.

Tuesday, January 13, 2015

Nintex Forms: Cannot open designer "An error occurred during an ajax call."

Recently I have installed the Nintex Workflow Forms and configured it.
I have activated the web application feature and site collection features and all, however when I try to customize a list forms using Nintex designer I started getting error message that says

 "An error occurred during an ajax call."

When I did IISReset, it seemed to have fixed it.

hope this small piece of information will save your time!

Monday, January 12, 2015

Nintex Workflow 2013, unable to publish workflow : soap:serverserver not able to process request object reference not set

Being a newbie with Nintex, I have installed and configured Nintex Workflow and Nintex Workflow Forms. easy to follow all the steps described on Nintex support page.

After doing all the necessary configuration, tried to create very simple one step workflow to test.

There I faced weird issue, I was able to save the workflow, however while publishing it was giving below error.

Error was very generic, wasted couple of hours to find the exact cause as in workflow logic there was nothing. simple one step workflow it was.

So pointer was going to configuration only, something in configuration is not proper which throwing this error.

Resolution :
1. Go to Central Admin
2. Click on Nintex Worklfow Management
3. Database setup -> Add Content Database ( I already configured it, still created new)
4. Configuration Database click Edit
5. Update the connection string with newly created database.

And we are good to go.

Hope this will save your time!

Tuesday, August 26, 2014

How to query SP2013 Managed metadata term store with JSOM

This post will show how to read the Taxonomy Term Store with JSOM.
Taxonomy Term store can be accessed in a SharePoint App, with permission scope of Taxonomy.
To be able to use the JSOM API for Taxonomy you need to reference SP.Taxonomy.js found in _layouts/15/ the best way to reference this would be in the document ready.

 $(document).ready(function () {  
 var scripRef = _spPageContextInfo.webServerRelativeUrl + "/_layouts/15/";  
 $.getScript(scripRef+ "SP.Runtime.js",  
 function () {  
 $.getScript(scripRef+ "SP.js", function () {  
 $.getScript(scripRef+ "SP.Taxonomy.js", function () {  
 context = SP.ClientContext.get_current();  
 //Call your code here.  

Read from Taxonomy

 function getTermStores() {  
   session = SP.Taxonomy.TaxonomySession.getTaxonomySession(context);  
   termStores = session.get_termStores();  
 termStoreEnum = termStores.getEnumerator();  
    var termStores = "TermStores: /n";  
    while (termStoreEnum.moveNext()) {  
     var currentTermStore = termStoreEnum.get_current();  
     var termStoreID = currentTermStore.get_id();  
     var termStoreName = currentTermStore.get_name();  
 termStores += "Name: " + termStoreName + " ID:" + termStoreID;  
 }, function(){  
 //failure loading.  

Tuesday, April 8, 2014

SharePoint Designer 2013 Workflow changes

Already, there are so many articles published about the new features and changes in SharePoint Designer 2013 that it’s a little late to write about this. But I think this would be useful.

There are many new functionalities and enhancements added into SharePoint designer 2013.
Added features allow designers to do more with workflows without requiring a developer to write custom code.

If you select SharePoint 2013 option while creating workflow, you will get the following list of new features

1. Stages

With 2013, concept of stage is introduced. It acts as containers in workflow, which allows one to structure the workflow from one stage to the other. Stages can be added to a workflow by clicking on Stage icon.

Key points for Stages:

  • All actions in the workflow must be contained in a stage
  • A stage can hold one or more workflow actions, and will also have only one Transition to stage area. 
  • The Transition to stage area defines how the workflow exits the stage after its actions have been processed. The stage can be configured to transition to another stage, or to end the workflow.
  • Workflows must have at least one stage, and it is not possible to nest stages in a workflow.
2. Actions

In 2013 new workflow actions are also introduced and they can be used while designing workflow.

Adding this action to a workflow allows a designer to create a single task, assign it to a specific user, and save the Outcome and TaskID values to workflow variables.

3. Assign a Task

Click on "Assign a task" action from actions menu, and the container displayed in above image, will show up.
Now click on thisuser, which will open the following dialogue.

4. Start a Task Process:
This action is the same as “Assign a Task” action, with the difference being that multiple participants can be assigned to the task being created. The participants can be assigned to the task one at a time (serial, meaning the first participant must respond to the task before the next participant is assigned, and so on.), or all participants can be assigned to the task at the same time (parallel).


5. Loops

There are two types of looping available: 

  • Loop n Times: Loop type allows a designer to create a looping condition where the actions contained in the loop container are executed a specified number of times.
  • The Loop with Condition: Loop type allows a designer to create a looping condition where the actions contained in the loop container are executed until a specified condition is met.

Key points for loops:
  1. Loops must be contained within a stage.
  2. A stage can be added inside a loop.
  3. Loops can have only one entry and only one exit point.
  4. Nested loops are also supported.
6. Call HTTP Web Service

This action allows you to call a REST-based web service without writing custom code. You specify the URL to the web service you wish to call, along with the HTTP method (GET, PUT, POST, and DELETE).

7. Visual Designer
In SharePoint Designer 2013 the Visual Designer is also introduced. This designer is only available for workflows on the 2013 platform, and you will need Visio 2013 Professional installed on your PC to have this available in SharePoint Designer.
When creating a workflow, you can switch to the Visual Designer by selecting it from the ribbon:

This will switch the view of the workflow you are designing to a view that looks a lot like a diagram in Visio:
With all these new features in the SharePoint designer, it has now become more powerful and strong enough for developer to not want to go for custom coding!

Thursday, February 6, 2014

Workflow gets canceled automatically with (500) Internal Server Error.

Workflow is getting cancel with the HTTP 500 error. 


RequestorId: 9dea9a29-bb82-214a-0000-000000000000. Details: RequestorId: 9dea9a29-bb82-214a-0000-000000000000. Details: An unhandled exception occurred during the execution of the workflow instance. Exception details: System.ApplicationException: HTTP 500 {"Transfer-Encoding":["chunked"],"X-SharePointHealthScore":["0"],"SPClientServiceRequestDuration":["30"],"SPRequestGuid":["9dea9a29-bb82-214a-92f0-943af4411ac2"],"request-id":["9dea9a29-bb82-214a-92f0-943af4411ac2"],"X-FRAME-OPTIONS":["SAMEORIGIN"],"MicrosoftSharePointTeamServices":[""],"X-Content-Type-Options":["nosniff"],"X-MS-InvokeApp":["1; RequireReadOnly"],"Cache-Control":["max-age=0, private"],"Date":["Fri, 31 Jan 2014 20:19:03 GMT"],"Server":["Microsoft-IIS\/7.5"],"X-AspNet-Version":["4.0.30319"],"X-Powered-By":["ASP.NET"]} at Microsoft.Activities.Hosting.Runtime.Subroutine.SubroutineChild.Execute(CodeActivityContext context) at System.Activities.CodeActivity.InternalExecute(ActivityInstance instance, ActivityExecutor executor

Probable solution/findings to verify:

1. Generally occurs with send email functionality in workflow.
2. Check outgoing email settings for the farm are correct.
3. Disabled firewall on the Exchange/SMTP server.
4. Check App management service is running, UPA is set up and  completed sync such that the user running the workflow has a profile.