Thursday 30 June 2016

SharePoint 2013 Crud Operations using AngularJS

Hi Guys !! Today I am gonna write post on using AngularJS in SharePoint. AngularJS is a Javascript MVC framework having 2 way databinding. detailed documentation on AngularJS is written here.

Please let me know for the better solutions using AngularJS in SharePoint as I am new to Angular JS and never used AngularJS in any of project. Simply because I am working on some other thing where AngularJS like excellent framework cant be used. This is just my curiosity to explore AngualrJS in my free time.

In this post I will be doing "Add List Item" and "Read List Items" operations using REST API through AngularJS Service. Since we are using REST API to interact with SharePoint List we will use AngularJS Service. AngularJS factory can also serve the same but using Service seems to be easy for me ;)

we will be creating 1 js file where our services will be defined. lets name it "svcLayer.js" which will have below code:-
brief explanation of the below code
1)  svcApp is an AppModel name which is added below in the HTML(i.e. View)
2) CustomSPService is a name of Service and function is created which has below 2 arguments
    a) $http verb is angularJS object to interact with WebServices.
    b) $q for promises in AngularJS. Promise is required because this would be an sync call and we don't know when our result will be ready

var ngApp = angular.module("svcApp", []);
 ngApp.service("CustomSPService", function CustomSPService($http, $q) {  
//fetchSPListItems  function will take rest service url in the parameter called query
   this.fetchSPListItems = function (query) {  
     var deferred = $q.defer();  
     $http({  
       url: query,  
       method: "GET",  
       headers: {  
         "accept": "application/json;odata=verbose",  
         "content-Type": "application/json;odata=verbose"  
       }  
     })  
       .success(function (data) {  
         deferred.resolve(data);  
       })  
       .error(function (result, status) {  
         deferred.reject(status);  
       });  
     return deferred.promise;  
   };  
//addSPListItems will have 2 parameters 1st rest service url, 2nd data to be posted to SharePoint
   this.addSPListItems = function (query,postDataObj) {  
     var deferred = $q.defer();  
     $http({  
       url: query,  
       method: "POST",  
       headers: {  
         "accept": "application/json;odata=verbose",  
         "X-RequestDigest": document.getElementById("__REQUESTDIGEST").value,  
         "content-Type": "application/json;odata=verbose"  
       },  
       data: JSON.stringify(postDataObj)  
     })  
       .success(function (data) {  
         deferred.resolve(data);  
       })  
       .error(function (result, status) {  
         deferred.reject(status);  
       });  
     return deferred.promise;  
   };  
 });  

Since I will be displaying the results of my List through content editor webpart I will be creating one HTML page which will be similar like below:-
brief explanation of the below code
1) while reading controlled I am injecting our above defined AngularJS Service and later on calling the methods of Service.

<!DOCTYPE html>  
 <html lang="en" xmlns="http://www.w3.org/1999/xhtml">  
 <head>  
   <meta charset="utf-8" />  
   <title></title>  
 </head>  
 <body ng-app="svcApp">  
   <div ng-controller="svcController">  
     <h2 ng-repeat="oitem in AllFetched">{{oitem.Title}} {{oitem.FirstName}} {{oitem.City}}</h2>  
     <input type="button" ng-click="AddSPItem()" value="Add Item" />  
   </div>  
 </body>  
 <script src="../Site%20Assets/JS/angular.js"></script>  
 <script src="../Site%20Assets/JS/svcLayer.js"></script>  
 <script type="text/javascript">  
   angular.module("svcApp").controller("svcController", function ($scope, CustomSPService) {  
     $scope.init = function () {  
       $scope.fetchAll();  
     }  
     $scope.fetchAll = function () {  
       console.log("fetchall Called");  
       CustomSPService.fetchSPListItems(_spPageContextInfo.webAbsoluteUrl +  
         "/_api/web/lists/getbytitle('UserList')/items")  
         .then(function (res) {  
           console.log(res);  
           $scope.AllFetched = res.d.results;  
         }, function (err) {  
           console.log(err);  
         })  
     }  
     $scope.AddSPItem = function () {  
       var itemType = "SP.Data.UserListListItem";  
       var vardata = {  
         '__metadata': { 'type': itemType },  
         'Title': 'Mr', 'FirstName': 'XYZ',  
         'City': 'Dubai'  
       };  
       CustomSPService.addSPListItems(_spPageContextInfo.webAbsoluteUrl +  
         "/_api/web/lists/getbytitle('UserList')/items", vardata)  
         .then(function (res) {  
           console.log('Success ' + res);  
           $scope.fetchAll();  
         }, function (err) {  
           console.log(err);  
         })  
     }  
     $scope.init();  
   });  
 </script>  
 </html>  

Saturday 28 May 2016

CSOM:TaxonomyFieldValueCollection returns null

Recently I came across a weird issue while reading TaxonomyField using Client Side Object Model.
I was using the below legacy and full proof working code for reading the value from ListItem
TaxonomyFieldValueCollection taxFieldValueColl = oitem[column] as TaxonomyFieldValueCollection;
I never had issues while using this code, but once this started and became nightmare for me.
Strange part was that same code use to work on removing and adding the dll reference of "Microsoft.SharePoint.Client.Taxonomy" only for the first time.
Believe I was not able to google it also as I don't even know which keyword I should use.

But finally I found one article here which really helped me lot and resolved my issue.
I would really urge to visit the above link and read it.
It was just a matter of using below code.
TaxonomyItem dummy = new TaxonomyItem(clientContext,null); 

Friday 22 April 2016

CSOM Error: Cannot complete this action. Please try again

Hi Guys,

Today i came across with the above error while doing add operation in SharePoint 2013 Online site using CSOM. Reason why I am sharing this is because, for me it was very weird during initial stage of troubleshooting as it says "Cannot complete this action."

The first thing hit into mind after this error was that "some updates must be happening to this Online site" but later on i realized that if updates are taking place then it will say "site is in read only mode....".

After that I debugged and find out that error was with one of the DateTime column which I was updating and reason was that it was having the value "01/01/0001".

Here strange part was that InnerException was null and to find out the exact error you have to dig inside the Exception object and somewhere you will find that Culprit Column Name.

Hope some one will be benefited out of it.

Thanks.

Tuesday 16 February 2016

SharePoint 2013 - Export Termstore to CSV using CSOM




 using Microsoft.SharePoint.Client;
 using Microsoft.SharePoint.Client.Taxonomy;  
 using System;  
 using System.Collections.Generic;  
 using System.Linq;  
 using System.Security;  
 using System.Text;  
 using System.Threading.Tasks;  
 namespace ExportTermStoreToCSV  
 {  
   class Program  
   {  
     static void Main(string[] args)  
     {  
       var sbCSV = new StringBuilder();  
       #region get Termstore Online  
       Console.Write("Enter Site URL:-");  
       string SiteUrl = Console.ReadLine();  
       ClientContext cc = new ClientContext(SiteUrl);  
       Console.Write("Enter User Name:-");  
       string Username = Console.ReadLine();  
       Console.Write("Enter Password:-");  
       string passwordOnline = Console.ReadLine();  
       var securePasswordOnline = new SecureString();  
       foreach (char c in passwordOnline)  
       {  
         securePasswordOnline.AppendChar(c);  
       }  
       cc.Credentials = new SharePointOnlineCredentials(Username, securePasswordOnline);  
       TaxonomySession taxonomySession = TaxonomySession.GetTaxonomySession(cc);  
       TermStore termStore = taxonomySession.GetDefaultSiteCollectionTermStore();  
       cc.Load(termStore,  
           store => store.Name,  
           store => store.Groups.Include(  
             group => group.Name,  
             group => group.TermSets.Include(  
               termSet => termSet.Name, termSet => termSet.Terms.Include(  
                 term => term.Name, term => term.TermsCount, term => term.LocalCustomProperties, term => term.Terms.Include  
                   (  
                   childTerm => term.Name,  
                   childTerm => term.TermsCount,  
                   childTerm => term.LocalCustomProperties,  
                   childTerm => term.Terms.Include(  
                     childTerm2 => term.Name,  
                     childTerm2 => term.TermsCount,  
                     childTerm2 => term.LocalCustomProperties,  
                     childTerm2 => term.Terms.Include(  
                         childTerm3 => term.Name,  
                         childTerm3 => term.TermsCount,  
                         childTerm3 => term.LocalCustomProperties,  
                         childTerm3 => term.Terms.Include(  
                           childTerm4 => term.Name,  
                           childTerm4 => term.TermsCount,  
                           childTerm4 => term.LocalCustomProperties,  
                           childTerm4 => term.Terms.Include(  
                             childTerm5 => term.Name,  
                             childTerm5 => term.TermsCount,  
                             childTerm5 => term.LocalCustomProperties,  
                             childTerm5 => term.Terms.Include(  
                               childTerm6 => term.Name,  
                               childTerm6 => term.TermsCount,  
                               childTerm6 => term.LocalCustomProperties)))))))  
             )  
           )  
       );  
       cc.ExecuteQuery();  
       if (taxonomySession != null)  
       {  
         if (termStore != null)  
         {  
           sbCSV.AppendLine("TermSetName, Level 1, Level 2, Level 3, Level 4, Level 5, Level 6, Level 7");  
           foreach (TermGroup group in termStore.Groups)  
           {  
             Console.WriteLine("Group " + group.Name);  
             sbCSV.AppendLine(group.Name + ",,,,,,,");  
             foreach (TermSet termSet in group.TermSets)  
             {  
               Console.WriteLine("TermSet " + termSet.Name);  
               sbCSV.AppendLine(group.Name + "," + termSet.Name + ",,,,,,");  
               foreach (Term term in termSet.Terms)  
               {  
                 // Writes root-level terms only.  
                 Console.WriteLine("Term " + term.Name);  
                 sbCSV.AppendLine(group.Name + "," + termSet.Name + "," + term.Name + ",,,,,");  
                 if (term.TermsCount > 0)  
                 {  
                   string str = group.Name + "," + termSet.Name + "," + term.Name;  
                   BindTermStore(term.Terms, str, sbCSV);  
                 }  
               }  
             }  
           }  
         }  
       }  
       #endregion  
       System.IO.File.WriteAllText(@"D:\Whatever.csv", sbCSV.ToString());  
     }  
     /// <summary>  
     /// Recursive method to check child terms  
     /// </summary>  
     /// <param name="termColl">TermCollection termColl</param>  
     /// <param name="str">string strTermName</param>  
     /// <param name="sbs">StringBuilder sbs</param>  
     private static void BindTermStore(TermCollection termColl, string str, StringBuilder sbs)  
     {  
       foreach (Term term in termColl)  
       {  
         // Writes root-level terms only.  
         Console.WriteLine("Term " + term.Name);  
         sbs.AppendLine(str + "," + term.Name);  
         if (term.TermsCount > 0)  
         {  
           string sss = str + "," + term.Name;  
           BindTermStore(term.Terms, sss, sbs);  
         }  
       }  
     }  
   }  
 }  

Friday 8 January 2016

SharePoint Custom Promoted Links

Creating custom promoted links webpart, which will get data from SharePoint Link List using REST



 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js" type="text/javascript"></script>  
 <style>  
   .imagecontainer a:visited {  
     color: white;  
   }  
   .imagecontainer a {  
     text-decoration: none;  
   }  
   /*for displaying text on image*/  
   .imagecontainer {  
     height: 110px;  
     width: 110px;  
     position: relative;  
     padding-left: 10px;  
     padding-top: 10px;  
   }  
   .imagecontent {  
     position: absolute;  
     left: 0;  
     top: 0;  
     height: 110px;  
     width: 110px;  
     padding-left: 10px;  
     padding-top: 10px;  
   }  
   .imagetext {  
     z-index: 100;  
     position: absolute;  
     color: white;  
     font-size: 12px;  
     background-color: rgba(0, 0, 0, 0.60);  
     width: 102px;  
     height: 35px;  
     bottom: 1px;  
     padding-left: 8px;  
     margin-bottom: -1px !important;  
     transition: height 1500ms;  
     -moz-transition: height 1500ms, -moz-transform 1500ms; /* Firefox 4 */  
     -webkit-transition: height 1500ms, -webkit-transform 1500ms; /*Safari and Chrome */  
     -o-transition: height 1500ms, -o-transform 1500ms; /* Opera */  
   }  
   .imagecontainer:hover .imagetext {  
     height: 110px;  
     transition: height 750ms;  
     -moz-transition: height 750ms, -moz-transform 750ms; /* Firefox 4 */  
     -webkit-transition: height 750ms, -webkit-transform 750ms; /*Safari and Chrome */  
     -o-transition: height 750ms, -o-transform 750ms; /* Opera */  
   }  
 </style>  
 <script type="text/javascript">  
   $(document).ready(function () {  
     GetTestLink();  
   });  
   function GetTestLink() {  
     var temURL = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('TestLink')/items";  
     $.ajax({  
       url: temURL,  
       method: "GET",  
       headers: {  
         "Accept": "application/json; odata=verbose",  
         "content-type": "application/json; odata=verbose"  
       },  
       success: function (data) {  
         var linkshtml = "";  
         var tempLength = data.d.results.length;  
         var j = 0  
         for (var i = 0; i < (data.d.results.length) / 3; i++) {  
           linkshtml += "<tr>";  
           if (i == 0) {  
             j = 0;  
           }  
           var k = (j + 3);  
           for (j; j < k && j < data.d.results.length; j++) {  
             linkshtml += "<td class='imagecontainer' ><img src='/SiteAssets/images.png' alt='' class='imagecontent'/><a class='imagetext' href='"  
             + data.d.results[j].URL.Url + "'>" + data.d.results[j].URL.Description + "</a></td>";  
           }  
           linkshtml += "</tr>";  
         }  
         $("#tblLinks").append(linkshtml);  
       },  
       error: function (jqxr, errorCode, errorThrown) {  
         alert(jqxr.responseText);  
       }  
     });  
   }  
 </script>  
 <div style="padding-bottom: 40px; border-width: 2px; border-color: #ccc; border-style: solid; border-radius: 4px">  
   <table id="tblLinks"></table>  
 </div>