Wednesday, 31 May 2017

SharePoint online / Office 365 – Deleting specific lists using CSOM through console application

Hi All,
 
In this article I’ll share the detailed steps for deleting specific lists based on content type IDs using CSOM in console application.


Scenario: In one of our SharePoint online project, we are creating multiple lists and associating our custom specific content type to those. But somehow lists are not getting created properly and most of those are corrupted. For some list content types are not associated. We all these operations were doing using Java Script Object Model (JSOM). In this case we need to then delete all these lists and then create again. Here we have option either using PowerShell script or CSOM. In these scenario, I always prefer CSOM since which is easy as compare to PowerShell and easy to implement. 

Here code is pretty simple, nothing complex there but sharing since if required then some time will be saved J


Steps for deleting the list using CSOM and console application:

1.      Create C# console application in Visual Studio. Here I am using Visual Studio 2017 community edition.

2.      Add the reference to following two client dlls

a.      Microsoft.SharePoint.Client.dll

b.      Microsoft.SharePoint.Client.Runtime.dll

To add these references we must need to install SharePoint Online Client Components SDK .

3.      Connect to O365:

a.      We are storing our SharePoint online site URL, user name and password in configuration file. Get the details to connect O365 as,


           //Read the details from config file – App.config

       string siteURL = ConfigurationSettings.AppSettings["siteURL"];

       string userName = ConfigurationSettings.AppSettings["userName"];

       string password = ConfigurationSettings.AppSettings["password"];


b.      Create the client context object and set the credentials as


  ClientContext clientContext = new ClientContext(siteURL);

    SecureString securePassword = new SecureString();


     foreach (char c in password.ToCharArray()) securePassword.AppendChar(c);


clientContext.Credentials = new SharePointOnlineCredentials(userName, securePassword);


4.      Load web object and get all lists as

                     //Load the web

                     Web web = clientContext.Web;

   clientContext.Load(web);

   //Get all lists

   ListCollection allList = web.Lists;  

  clientContext.Load(allList);


  clientContext.ExecuteQuery();

5.      Next step is to find the lists which we need to delete

//Get all the lists whose content type is "MyContentType" and store in one array list

ArrayList listArray = new ArrayList();

//Below is the content type id of which we need to find the lists and delete those

string myContentTypeID = "0x01007931F4F9F69E0443972158D57498131A00A96BC22822FD7D40817DBAB3343D80AA";


//Loop through all the lists and check for their content type ids

            foreach(List _list in allList)

            {

                //Get all associated content types to the list

                ContentTypeCollection ctCollection = _list.ContentTypes;
   //Find our content type - Here, important point is even though our content   type is not associated, it dosent return null


//It returns new CT object but "ServerObjectIsNull" property returns false in case content type is not associated.

          ContentType ct = _list.ContentTypes.GetById(myContentTypeID);

          clientContext.Load(ct);

          clientContext.ExecuteQuery();


             bool? isCT = ct.ServerObjectIsNull;



 //Check if our content type with given id is associated or not if(isCT.ToString().ToLower().Equals("false",

StringComparison.InvariantCultureIgnoreCase))

                {

                    listArray.Add(_list.Title);

                }

}//foreach(List _list in allList)


//Now loop through all the array and find the list from above list collection object and call "DeleteObject" method


            for (int i = 0; i < listArray.Count; i++)

            {

                    string listTitle = listArray[i].ToString();

                    Console.WriteLine("List Deleting - :" + listTitle);

                    allList.GetByTitle(listArray[i].ToString()).DeleteObject();

                    Console.WriteLine("List deleted successfully " + listTitle);

                    web.Update();

                    clientContext.ExecuteQuery();

  } // for (int i = 0; i < listArray.Count; i++)


Thanks!


Enjoy Reading :)


As usual any comment / suggestions / feedback / questions always welcome :)

Tuesday, 30 May 2017

Revisiting concepts of JavaScript for SharePoint / Office 365 developer - Part 2 - JavaScript Namespaces

Hi All,

In this article I’ll explain the details of JavaScript namespaces, which should know for SharePoint / Office 365 developer who uses the JavaScript Object Model(JSOM) for SharePoint / Office 365 development.

Background: I have written one article regarding JavaScript variables (http://prashamsabadra.blogspot.in/2016/11/revisiting-concepts-of-javascript-for.htmlhttp://prashamsabadra.blogspot.in/2016/11/revisiting-concepts-of-javascript-for.html ). In this article we will discuss regarding JavaScript namespaces. I feel it’s really very important to understand the concept of namespaces while working on JSOM or SharePoint hosted apps.


Global Namespace:

1. By default JavaScript doesn’t provide namespace. 

2. Anything we write in JavaScript file and placed into global namespace by default including all variables and functions.

3. In browser, global namespace container is “Window” object. 

4. Issue with directly using global namespaces: Since whatever we write to JavaScript file goes to global namespaces, there might be chances that naming conflicts appear. For example, if on my site if we are loading couple of JavaScript files, there might be chances that same function name or same variable name there in different files. Which will cause the conflict and code will not behave correctly. Solution to this problem is using namespaces in our JavaScript code. 

Custom Namespace:

1. To address issue with global namespace as mentioned above in point 4 under Global Namespace section, we can create our own custom namespaces in JavaScript.

2. Custom namespace is nothing but the object defined within the global namespace.

3. Defining custom namespace:

//Custom NameSpace
             var Validations = window.Validations || {};

Here, we are creating custom namespace “Validations” under global namespace object  “window”.  It checks if global variable “Validations” is exist already then set the reference to it otherwise create new global variable.

4. We can add our methods/functions then under namespace “Validations” as 

Validations.validateEmpty = function (){
              // Method code goes here
             }

Here, we have created a method called “validateEmpty()” under namespace “Validations”.  So now even though if same method is in another JS file on the same page then also conflict will not occur. Since here our method is isolated by our custom namespace. 

While calling “validateEmpty()” method we need to call it by using namespace like Validations.validateEmpty();

5. Similarly we can create our variables in our custom namespace like

               //Custom NameSpace
               var Constants = window.Constants || {};

              and then we can create variables under our custom Constants namespace like

              Constants.cssFileURL = “My CSS File URL”;

This is very common scenario where we can have all our validations methods in “Validations” namespace, all constants in “Constants” namespace and all SharePoint list CRUD operations in “SharePointCRUD” namespace. In this way our code will be isolated and there will be no chances of code conflicts. 

Advantages of using Namespaces:

1. Code Isolation: No code conflicts with other code on page in case multiple JavaScript files are loaded or any third part JavaScript files referred. In SharePoint online, SharePoint itself loads its JavaScript files so there are high chances of conflicts. To better solution is to use our custom namespaces.

2. Clean code, improves code readability. Code maintenance is easy. 

Thanks!

Enjoy Reading J

As usual any comment / suggestions / feedback / questions always welcome :)

Monday, 29 May 2017

Office 365 / SharePoint online – Getting current user profile image (picture url) without callback in JSOM

Hi All,

In this article I’ll share one little finding which I recently found. This is related to the current user profile image which we need to show on our SharePoint online site in our custom master page. Generally in JSOM whenever we call / load something we need call backs. So we need to depend on either respective success or failure method. Here I’ll share how we can get current user or any user profile image without callback.

Background: In our one of the SharePoint online site, we need to show current logged in user profile image.  We have our custom master page. So we need to basically get the current user property – “Picture URL” and render. Since there is no another option we could found we have implemented using JSOM. So code is really simple as shown below.

Note: Here only shared sample code and not the complete one.

We have written one method “fetchUserDetails” which loads the user details as below


SP.SOD.executeOrDelayUntilScriptLoaded(fetchUserDetails, 'SP.UserProfiles.js');

     var userProfileProperties;

     function fetchUserDetails() {

         //Get Current Context  
         var clientContext = new SP.ClientContext.get_current();

         //Get Instance of People Manager Class
         var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);

         //Get properties of the current logged in user
         userProfileProperties = peopleManager.getMyProperties();
           
         //Load all the properties.
         clientContext.load(userProfileProperties);

         //Execute the Query.
         clientContext.executeQueryAsync(onfetchUserDetailsSuccess,onfail);

     } // fetchUserDetails

Success method as below


function onfetchUserDetailsSuccess () {

           //Get picture URL
           var pictureUrl = userProfileProperties.get_pictureUrl();

           //Currently just showing in alert
           alert(pictureUrl);    
} // onfetchUserDetailsSuccess

Disadvantage of above approach: There is nothing wrong in above approach but then we need to wait for the call back and then we get the profile image for current user. It’s not like that directly we will get the current user profile image. So it’s also a bit lazy loading.

New approach: Just while googling for some issue, I found that there is delve service which directly returns the any user profile image without call back. Service name is “DelveApi.ashx” and way to call it as


// Get current site URL
    var currentSiteURL = _spPageContextInfo.siteAbsoluteUrl;

    //Form the delve service URL
    var delveServiceURL = currentSiteURL +  "/_vti_bin/DelveApi.ashx/people/profileimage?userId=" + _spPageContextInfo.userLoginName + "&size=L";

We could also mention the size (L, M and S). Actually this service download the respective image as per specified the Size. So we could either use “div” tag or “img” tag and set the “src” property of them. No dependency on callback or no need to handle the failed method.

One more benefit of using this approach is, if we know the login name of the user then we can easily download there profile image by specifying respective login name to userId parameter. Currently here we are passing current logged in user’s login name. This is useful where in some scenarios we need show the users listing.

I hope you will find this little finding useful.


Thanks!

Enjoy Reading!

As usual any comment / suggestions / feedback / questions always welcome :)