Monday 7 December 2015

SharePoint Hosted App:- post data to External Webservice

This blog will explain how to post data to an external web-service from SharePoint Online(Office 365) site using SharePoint Hosted Apps.

Here I am gonna use Napa tool to create SharePoint Hosted Apps.
Brief introduction on NAPA tools- it is a browser enabled light weighted tool introduced in SharePoint 2013 to create SharePoint Hosted Apps. Reason why i said it is light weighted because this itself is an App which can be added to site and can be used to create an App.
In my site I have already added NAPA tools and it can be seen under Site Contents

Just click on NAPA which will redirect you to the similar screen like below to create an APP.

give a meaningful name(here I had given- CallExternalWebService) and click on Create. 
Once it is created you will see the entire project structure like below



Now open App.js and replace the code with the below code.

//start app.js snippet  
 'use strict';  
 var context = SP.ClientContext.get_current();  
 var user = context.get_web().get_currentUser();  
 (function () {  
   // This code runs when the DOM is ready and creates a context object which is  
   // needed to use the SharePoint object model  
   $(document).ready(function () {  
     getUserName();  
     CallExternalWebServiceDemo();  
   });  
   // This function prepares, loads, and then executes a SharePoint query to get  
   // the current users information  
   function getUserName() {  
     context.load(user);  
     context.executeQueryAsync(onGetUserNameSuccess, onGetUserNameFail);  
   }  
   // This function is executed if the above call is successful  
   // It replaces the contents of the 'message' element with the user name  
   function onGetUserNameSuccess() {  
     $('#message').text('Hello ' + user.get_title());  
   }  
   // This function is executed if the above call fails  
   function onGetUserNameFail(sender, args) {  
     alert('Failed to get user name. Error:' + args.get_message());  
   }  
   function CallExternalWebServiceDemo() {  
     //url of the webservice  
     var webserviceURL = "http://xyz.com/api/postsomething";  
     $.ajax({  
       url: "../_api/SP.WebProxy.invoke",  
       type: "POST",  
       data: JSON.stringify(  
         {  
           "requestInfo": {  
             "__metadata": { "type": "SP.WebRequestInfo" },  
             "Url": webserviceURL,  
             "Method": "POST",  
             "Headers": {  
               "results": [{  
                 "__metadata": { "type": "SP.KeyValue" },  
                 "Key": "Accept",  
                 "Value": "application/json",  
                 "ValueType": "Edm.String"  
               }, {  
                 "__metadata": { "type": "SP.KeyValue" },  
                 "Key": "Content-Type",  
                 "Value": "application/json",  
                 "ValueType": "Edm.String"  
               }]  
             },  
             "Body": "in json format"  
           }  
         }),  
       headers: {  
         "Accept": "application/json;odata=verbose",  
         "Content-Type": "application/json;odata=verbose",  
         "X-RequestDigest": $("#__REQUESTDIGEST").val()  
       },  
       success: function (data) {  
         alert("Sucess");  
       },  
       error: function (jqxr, errorCode, errorThrown) {  
         alert(jqxr.responseText);  
       }  
     });  
   }  
 })();  
 ////end app.js snippet

Now open settings by clicking on it as shown below


clicking on setting will open screen as shown below

now add your end point and click on apply/
If you are creating SharePoint Hosted App using Visual Studio then "Remote Endpoints" are available in AppManifest.xml.

Now run the app which will automatically deploy and will add it in your site.

Thanks.

Thursday 3 December 2015

Read current user profile properties from UserProfileService using REST API

This blog will showcase how to read current user(Logged In User) profile properties using Rest API in SharePoint.

var uspURL= _spPageContextInfo.webAbsoluteUrl + "/_api/SP.UserProfiles.PeopleManager/GetMyProperties";  
     $.ajax({  
       url: uspURL,  
       method: "GET",  
       headers: {  
         "Accept": "application/json; odata=verbose",  
         "content-type": "application/json; odata=verbose"  
       },  
       success: function (data) {  
         var userProfileDetails = data;  
         var propertyKey="XYZ";  
         var PropertyValuePair = $.grep(userProfileDetails.d.UserProfileProperties.results, function (v) {  
           return v.Key === propertyKey;  
         });  
         var propertyValue = PropertyValuePair[0].Value  
       },  
       error: function (jqxr, errorCode, errorThrown) {  
         alert(jqxr.responseText);  
       }  
     });  

_spPageContextInfo SharePoint developer's best friend

_spPageContextInfo is always used by me whenever I am writing any SharePoint Client Site Code. It has a very useful properties which i will put it down in tabular format for better understanding and hence i call it as a SharePoint Developer's best friend.




Working with page layouts in SharePoint 2013

Design Manager:- my friend in SharePoint 2013 to work with Page Layouts and Master Page.
Certain new and interesting stuffs are introduced in SharePoint 2013 to work with page layouts using Design Manager.

First thing on which we should focus is that now every page layout will have two component i.e. first .aspx which is used by SharePoint and second is .html which is used to edit the pagelayout in any html designer. Basically this concept was introduced for the ease of designing.

Lets start with creating new page layout. Every page layout is associated with some Page content type and hence I have a habit of creating my own content type while creating new page layouts for several reasons like ease of searching, modification etc.
Here I have created new content type from Article Page content type which is inherited from Page Layout Content Type.

First goto DesignManager which is available in Publishing Site.


Clicking on publishing site will navigate to the below page.

Here we can create our own page layout. Creating new page layout will ask for layout name, master page and which content type to be used.


Now it’s time to customize the Page layout. Download the page layout into your filesystem and start playing with it. Downloading from DesignManager will download the HTML file.
In HTML we can see two important divs which are mentioned below:-
1) <div data-name="EditModePanelShowInEdit">:- Content of this div is visible only when it is Edit Mode.
2)  <div data-name="EditModePanelShowInRead">:- Content of this div is visible only when it is Read Mode. In short this is the div where actually end user will be interacting.

In my case end user will only read news and will be able to navigate to the archived contents.
Hence in ShowInRead I have created the blank skeleton i.e the approved UI for end user. Rest everything I did it using javascript and jquery.
Reference of javascript files has to given in "PlaceHolderAdditionalPageHead".

Wednesday 2 December 2015

Read selected Metadata tagging across SharePoint SiteCollection

Couple of months back I was asked to generate the report of one Metadata Field present in SharePoint Online site i.e where and all that column is used along with the tagged value, item url, list name and blah blah blah..
Initially I thought of using SharePoint Search API but due to following drawbacks i stepped back:-

  • If any List or Library are selected not display records in search, then i wont be able to get it
  • Item level permission.
Hence i decided to write a CSOM code, as report has to be submitted in couple of hours. Code is quite simple and easy to understand, it would have become reusable if I would have made it recursive. But in may case it was not required as there wasn't any sub site under any site ;)


static void Main(string[] args)  
     {  
       Console.WriteLine("Enter Online Site URL");  
       string siteUrl = Console.ReadLine();  
       Console.WriteLine("Enter User Name");  
       string userName = Console.ReadLine();  
       Console.WriteLine("Enter Password");  
       string password = Console.ReadLine();  
       Console.WriteLine("Enter Metadata Column's Internal Name");  
       string column = Console.ReadLine();  
       SecureString securePass = new SecureString();  
       foreach (char c in password)  
       {  
         securePass.AppendChar(c);  
       }  
       StringBuilder strBldr = new StringBuilder();  
       strBldr.AppendLine("SiteName,ItemUrl,Tags");  
       using (ClientContext ctx = new ClientContext(siteUrl))  
       {  
         ctx.Credentials = new SharePointOnlineCredentials(userName,  
           securePass);  
         Web oweb = ctx.Site.RootWeb;  
         ctx.Load(oweb);  
         ctx.Load(oweb.Webs);  
         ctx.Load(oweb.Lists);  
         ctx.ExecuteQuery();  
         #region Read root level lists  
         //This can be made recursive also  
         foreach (List olist in oweb.Lists)  
         {  
           ctx.Load(olist);  
           ctx.Load(olist, l => l.DefaultViewUrl);  
           if (olist.ContainsField(column))  
           {  
             ListItemCollection ocoll = olist.GetItems(CamlQuery.CreateAllItemsQuery());  
             ctx.Load(ocoll);  
             ctx.ExecuteQuery();  
             foreach (ListItem oitem in ocoll)  
             {  
               TaxonomyFieldValueCollection taxFieldValueColl = oitem[column] as TaxonomyFieldValueCollection;  
               string tags = string.Empty;  
               // Loop through all the taxonomy field values  
               foreach (TaxonomyFieldValue taxFieldValue in taxFieldValueColl)  
               {  
                 // Display the taxonomy field value  
                 Console.WriteLine(taxFieldValue.Label);  
                 tags += RemoveComma(taxFieldValue.Label, "-") + ";";  
               }  
               if (!string.IsNullOrEmpty(tags))  
               {  
                 strBldr.AppendLine(RemoveComma(oweb.Title, "-") +  
                   "," + RemoveComma(Convert.ToString(oitem.FieldValues["FileRef"]), "%2C") + "," + tags);  
               }  
             }  
             Console.WriteLine("Site Title - " + oweb.Title + ", List Title - " + olist.Title + " Item Count - " + olist.ItemCount);  
           }  
         }  
         #endregion  
         Console.WriteLine("Root Web Title - " + oweb.Title);  
         //read each site and list  
         foreach (Web web in oweb.Webs)  
         {  
           ctx.Load(web);  
           ctx.Load(web.Lists);  
           ctx.ExecuteQuery();  
           foreach (List lis in web.Lists)  
           {  
             ctx.Load(lis);  
             ctx.Load(lis, k => k.DefaultViewUrl);  
             if (lis.ContainsField(column))  
             {  
               Console.WriteLine("Site Title " + web.Title + ", List Title - " + lis.Title + " Item Count - " + lis.ItemCount);  
               ListItemCollection ocoll = lis.GetItems(CamlQuery.CreateAllItemsQuery());  
               ctx.Load(ocoll);  
               ctx.ExecuteQuery();  
               foreach (ListItem oitem in ocoll)  
               {  
                 TaxonomyFieldValueCollection taxFieldValueColl = oitem[column] as TaxonomyFieldValueCollection;  
                 string tags = string.Empty;  
                 // Loop through all the taxonomy field values  
                 foreach (TaxonomyFieldValue taxFieldValue in taxFieldValueColl)  
                 {  
                   // Display the taxonomy field value  
                   Console.WriteLine(taxFieldValue.Label);  
                   tags += RemoveComma(taxFieldValue.Label, "-") + ";";  
                 }  
                 if (!string.IsNullOrEmpty(tags))  
                 {  
                   strBldr.AppendLine(RemoveComma(web.Title, "-") +  
                     "," + RemoveComma(Convert.ToString(oitem.FieldValues["FileRef"]), "%2C") + "," + tags);  
                 }  
               }  
             }  
           }  
         }  
         System.IO.File.WriteAllText(@"D:\" + column + ".csv", strBldr.ToString());  
       }  
     }  
     /// <summary>  
     /// This method will replace comma in the given string with given charcter  
     /// </summary>  
     /// <param name="inputValue"></param>  
     /// <param name="replace"></param>  
     /// <returns></returns>  
     private static string RemoveComma(string inputValue, string replace)  
     {  
       string tempInputValue = inputValue.Replace(",", replace);  
       return tempInputValue;  
     }