Perform Basic Admin Operations using CSOM in SharePoint Online


Introduction

This post will focus on how to make use of SharePointOnlineCredentials class to authenticate to SharePoint Online from your host machine using a console application. In this article I will give you a walk through of some of the basic administration stuff that can now be achieved using CSOM. Previously this was possible only using Powershell and SharePoint Online (SPO) commandlets but now we have CSOM as an option available as well.

Though we can use CSOM from an app but in the below scenarios I will be implementing the same using Console Application to keep things simple.


How does authentication happen

The authentication process with CSOM in SharePoint Online has been greatly simplified in SharePoint 2013 with the introduction of the SharePointOnlineCredentials class. With the use of this class, we simply need to pass the email id for login into our SharePoint Online site and the password in the SecureString format. This class has been introduced as a part of Microsoft.SharePoint.Client.dll.


Prerequisites

Before starting with the actual code you need to ensure that the following dll's are in place

  1. Microsoft.SharePoint.Client.dll
  2. Microsoft.SharePoint.Client.Runtime.dll
  3. Microsoft.Online.SharePoint.Client.Tenant.dll

The first two dll's are available in the ISAPI folder of your 15 hives whereas for the third dll i.e. Microsoft.Online.SharePoint.Client.Tenant.dll , you need to download the SharePoint Server 2013 Client Components SDK available for download here. Once you have downloaded and installed this SDK you will find a folder created in your Program Files having the dll at the location "C:\Program Files\SharePoint Client Components\Assemblies".

Once you have the dll in place, you are good to start with the actual implementation.


Scenarios

Let me first discuss with you the various scenarios I will be covering here using CSOM in a console application.

  1. Fetch all available web templates for creating a site collection
  2. Create a site collection
  3. Fetch all site collections
  4. Delete a site collection
  5. Restore a deleted site collection
  6. Permanently delete a site collection

To start with, before we do any of the above mentioned operations, below is the screenshot depicting the site collections created OOB when we create a fresh tenant in SharePoint Online. As you can see below, all the site collections are available by default and none of them is created through our code.

Now, lets get started with the actual interesting stuff here. Please note that I will be focusing more on code rather than explanations as the code itself is self explanatory.

Scenario 1 : Fetch all available web templates for creating a site collection in SharePoint Online

While doing a POC on creating a publishing site using the CSOM in SharePoint Online context, I observed that the template id that we normally use in On-premise implementation was not working with SharePoint Online. So to understand what all options for web template id's we have in SharePoint Online, I did a small POC on fetching all the available web templates and the knowledge we will use in creating site collections out of those templates. Having said that let me dive directly into the code. The below code snippet will fetch a list of all the available web templates in your SharePoint Online using which you can create a site collection.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.SharePoint.Client;
using System.Security;
  
namespace FetchAllWebTemplates
{
  class Program
  {
    static void  Main(string[] args)
    {
       using (ClientContext tenantContext = new ClientContext("https://yoursite-admin.sharepoint.com/"))
       {
          SecureString passWord = new  SecureString();
          foreach (char c in "yourpassword".ToCharArray())
                passWord.AppendChar(c);
          tenantContext.Credentials = new  SharePointOnlineCredentials("admin@yoursite.onmicrosoft.com", passWord);
                     var tenant = new  Tenant(tenantContext);
  
          SPOTenantWebTemplateCollection spoWebTemplateCollection = tenant.GetSPOTenantWebTemplates(1033, 15);
          tenantContext.Load(spoWebTemplateCollection);
          tenantContext.ExecuteQuery();
          foreach (SPOTenantWebTemplate webTemplate in spoWebTemplateCollection)
          {

              Console.WriteLine(webTemplate.Name);
          }
          Console.ReadLine();
        }
    }
  }
}

The code above is self explanatory but let me give a little explanation around the same. If you have a look at the above code snippet, first of all I have created a client context of the tenant admin site that gets created when we register to Office 365. After generating the client context, we need to pass credentials of the admin to the SharePointOnlineCredentials class that will be used for authenticating to SharePoint Online. Note the constructor of this class accepts the login email id of the tenant administrator in this case and an encrypted password in SecureString format. We need to assign these credentials to the tenant client context. Once we are authenticates to SharePoint Online, we create the tenant object based on the client context. Having given the background to the basic steps, next comes are main requirement in picture here i.e. to fetch a list of available web templates. In CSOM there is a method called GetSPOTenantWebTemplates that accepts two parameters - the locale id and the compatibility level. Using this method we can fetch all the templates available for the site collection in the tenant. When we run the above console application, we get all the available web templates for SharePoint Online. As per MSDN below is the constructor for the same.

public SPOTenantWebTemplateCollection GetSPOTenantWebTemplates( 
    uint localeId, 
    int compatibilityLevel 
) 

As you can see in the above snippet that it accepts two parameters

  1. localeId : The locale identifier for the web templates to be retrieved like 1033
  2. compatibilityLevel : Latest Product Version with which the web templates are compatible i.e. 15 here

Have a look at the below screenshot. It shows list of all the available web templates in SharePoint Online.

As you can see in the above screenshot, for publishing site the available web template id is "BLANKINTERNETCONTAINER#0".

Scenario 2: Create a site collection

Having the background to all the available web templates, we can create a site collection out of those available templates. The initial steps to create a site collection in SharePoint Online are the same i.e.

  1. Obtain ClientContext for the tenant admin site.
  2. Convert your password into SecureString format required to pass to the SharePointOnlineCredentials constructor.
  3. Pass credentials to the client context Credentials property using SharePointOnlineCredentials object.
  4. Create a tenant out of the client context.

Now after you have done all these things, you need to create a new site collection. Microsoft has provided a method called CreateSite that accepts SiteCreationProperties object as an input and creates a site new site collection based on the same. Below is the constructor for the CreateSite method

public virtual  SpoOperation CreateSite( 
    SiteCreationProperties siteCreationProperties 
) 

As you can see above that CreateSite method accepts one parameter i.e. SiteCreationProperties. It is this SiteCreationProperties that set the initial properties when a new site collection gets created.  Refer to the below link to have a look at the list of exposed properties that you can set.

http://msdn.microsoft.com/en-us/library/microsoft.online.sharepoint.tenantadministration.sitecreationproperties_properties(v=office.15).aspx

Now, in the code snippet below, you might observe that I am making use of IsComplete property on the SpoOperation object. First let me explain briefly about SpoOperation class.  Basically, any operation we perform on a site collection represents an SpoOperation. So when we call the CreateSite method on the tenant, it will return an SpoOperation that will hold the information about site collection creation operation. Coming back to the code, we have made use of IsComplete property to check whether the operation has been completed or not. Have a look at the below links for more details

http://msdn.microsoft.com/en-us/library/office/microsoft.online.sharepoint.tenantadministration.spooperation.iscomplete(v=office.15).aspx

http://msdn.microsoft.com/en-us/library/microsoft.online.sharepoint.tenantadministration.spooperation(v=office.15).aspx

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.SharePoint.Client;
using System.Security;
 
namespace SPOTenantCreation
{
 class Program
   { 
   static void  Main(string[] args)
     {      
       using (ClientContext tenantContext =  new  ClientContext("https://yoursite-admin.sharepoint.com/"))
   {
    SecureString passWord = new  SecureString();
    foreach (char c in "yourpassword".ToCharArray())
              passWord.AppendChar(c);


    tenantContext.Credentials = new  SharePointOnlineCredentials("admin@yoursite.onmicrosoft.com", passWord);
 
    var tenant = new  Tenant(tenantContext);
    var siteCreationProperties = new  SiteCreationProperties();
    siteCreationProperties.Url = "https://yoursite.sharepoint.com/sites/SiteA";           siteCreationProperties.Title =     "Publishing Site Created from Code"    ;   
           siteCreationProperties.Owner = "admin@yoursite.onmicrosoft.com";
          siteCreationProperties.Template = "BLANKINTERNETCONTAINER#0";           siteCreationProperties.StorageMaximumLevel = 100;   
   siteCreationProperties.UserCodeMaximumLevel = 50;
 
    //Create the SiteCollection
    SpoOperation spo = tenant.CreateSite(siteCreationProperties);
 
    tenantContext.Load(tenant);
 
    //We will need the IsComplete property to check if the provisioning of the Site Collection is complete.
    tenantContext.Load(spo, i => i.IsComplete);
    tenantContext.ExecuteQuery();
 
    //Check if provisioning of the SiteCollection is complete.
    while (!spo.IsComplete)
    {
      //Wait and then try again
      System.Threading.Thread.Sleep(3000);
      spo.RefreshLoad();
      tenantContext.ExecuteQuery();
    }
 
    Console.WriteLine("SiteCollection Created.");
                       Console.ReadLine();

    }
      }
   }

}

In the below screenshot please find the newly created site collection using our code sample above.

Scenario 3 : Fetch All Site Collections

 

Next code snippet which I will be discussing about is around fetching all the site collections. At times you need to know what all site collections exist in your office 365 tenant. Again, the basic steps are the same.

  1. Obtain ClientContext for the tenant admin site.
  2. Convert your password into SecureString format required to pass to the SharePointOnlineCredentials constructor.
  3. Pass credentials to the client context Credentials property using SharePointOnlineCredentials object.
  4. Create a tenant out of the client context.

Now once you have done all the above things in your code, the change comes around the Tenant method that you will be using to fetch the site collections. In this case we will make use of Tenant.GetSiteProperties method that helps in fetching properties for all the sites in the tenant. Below is the constructor for the GetSiteProperties method

 

public virtual   SPOSitePropertiesEnumerable GetSiteProperties( 
 
    int startIndex, 
 
    bool includeDetail 
 
)

Below is the link to refer to all the available site properties that you can access

http://msdn.microsoft.com/en-us/library/microsoft.online.sharepoint.tenantadministration.siteproperties_properties(v=office.15).aspx

Accessing the title property for each item returned in the collection will give us the site collection title.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.SharePoint.Client;
using System.Security;
namespace FetchAllSiteCollections
{
    class Program
    {
        static void  Main(string[] args)
        {
            using(ClientContext tenantContext = new  ClientContext("https://yoursite-admin.sharepoint.com/"))
            {
                SecureString password = new  SecureString();
                foreach (char c in "yourpassword".ToCharArray())
                    password.AppendChar(c);
                tenantContext.Credentials = new  SharePointOnlineCredentials("admin@yoursite.onmicrosoft.com", password);
                var tenant = new  Tenant(tenantContext);
                SPOSitePropertiesEnumerable sitePropEnumerable = tenant.GetSiteProperties(0, true);
                tenantContext.Load(sitePropEnumerable);
                tenantContext.ExecuteQuery();
                foreach(SiteProperties property in  sitePropEnumerable)
                {
                    Console.WriteLine(property.Title);
 
                }
                Console.ReadLine();
            }
        }
    }
}

Below is the screenshot depicting title of all the fetched site collections. You can modify the code snippet to show whatever properties that you want.

  

Scenario 4 : Delete a Site Collection

Next, I will show how to delete a site collection. Now in the above steps we have our site collection created using CSOM in SharePoint Online. Now we will remove this site from the list. For this again the basic steps are the same. The difference comes with the method that we will be using to delete the site collection. We will make use of Tenant.RemoveSite method that will delete the site collection from the list of all the sites in the tenant. However this deleted site collection is not permanently deleted and is pushed to the recycle bin from where it can still be restored.

Below is the constructor for the RemoveSite method

 

public virtual   SpoOperation RemoveSite( 
 
    string siteUrl 
) 

 
As you can see in the above snippet, it accepts the site url as a parameter which is the url of the site collection that we want to delete.

In the below code snippet after deleting the site collection I am trying to fetch the deleted site collection using GetSitePropertiesByUrl method. If this method throws an exception that means our site is deleted. For more details on this method have a look at below link for reference

http://msdn.microsoft.com/en-us/library/microsoft.online.sharepoint.tenantadministration.tenant.getsitepropertiesbyurl(v=office.15).aspx

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.SharePoint.Client;
using System.Security;
using System.Threading;
namespace DeleteSiteCollection
{
    class Program
    {
        static void  Main(string[] args)
        {
            using (ClientContext tenantContext = new ClientContext("https://yoursite-admin.sharepoint.com/"))
            {
                SecureString password = new  SecureString();
                foreach (char c in "yourpassword".ToCharArray())
                    password.AppendChar(c);
                tenantContext.Credentials = new  SharePointOnlineCredentials("admin@yoursite.onmicrosoft.com", password);
                var tenant = new  Tenant(tenantContext);
                SpoOperation spoOperation = tenant.RemoveSite("https://yoursite.sharepoint.com/sites/SiteA");
 
                tenantContext.Load(spoOperation);
                tenantContext.ExecuteQuery();
 
                Console.WriteLine("Time: " + DateTime.Now);
                while (!spoOperation.IsComplete)
                {
                    Thread.Sleep(3000);
                    tenantContext.Load(spoOperation);
                    tenantContext.ExecuteQuery();
                     
                }
                Console.WriteLine("Time: " + DateTime.Now);
                Console.WriteLine("Verify that site no longer show up in getSiteProperties");
                try
                {
                    SiteProperties site = tenant.GetSitePropertiesByUrl("https://yoursite.sharepoint.com/sites/SiteA", false);
                    tenantContext.Load(site);
                    tenantContext.ExecuteQuery();
                    Console.WriteLine("Site is not deleted");
                }
                catch (ServerException e)
                {
                    Console.WriteLine("Cannot find the active site: " + e.Message);
                }
                Console.ReadLine();
            }
        }
    }
}

Below screenshot shows the site collection created from our code as deleted in the list of available site collections.

 

Scenario 5 : Restore a deleted site collection

 

As I mentioned above, RemoveSite will delete a site collection but still the deleted site can be restored from the recycle bin. The below code snippet will help in restoring the deleted site collection from the Recycle Bin. Again the basic steps are the same till we obtain the Tenant object. Once we have the Tenant object we make use of RestoreDeletedSite method to restore the deleted site. The constructor for the same is as below

 

public virtual   SpoOperation RestoreDeletedSite( 
  
    string siteUrl 
  
)

 
As you can see in the above snippet, the method accepts the site url as a parameter which is the url of the site collection that we want to restore.

After making call to the RestoreDeletedSite method, make a call to the GetSitePropertiesByUrl method to ensure that you have successfully restored the deleted site collection from the recycle bin.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.SharePoint.Client;
using System.Security;
using System.Threading;
namespace RestoreDeletedSiteCollection
{
    class Program
    {
        static void  Main(string[] args)
        {
            using (ClientContext tenantContext = new ClientContext("https://yoursite-admin.sharepoint.com/"))
            {
                SecureString password = new  SecureString();
                foreach (char c in "yourpassword".ToCharArray())
                    password.AppendChar(c);
                tenantContext.Credentials = new  SharePointOnlineCredentials("admin@yoursite.onmicrosoft.com", password);
                var tenant = new  Tenant(tenantContext);
                SpoOperation spoOperation = tenant.RestoreDeletedSite("https://yoursite.sharepoint.com/sites/SiteA");
 
                tenantContext.Load(spoOperation);
                tenantContext.ExecuteQuery();
 
                Console.WriteLine("Time: " + DateTime.Now);
                while (!spoOperation.IsComplete)
                {
                    Thread.Sleep(3000);
                    tenantContext.Load(spoOperation);
                    tenantContext.ExecuteQuery();
                     
                }
                Console.WriteLine("Time: " + DateTime.Now);
                Console.WriteLine("Verify that site is restored");
                try
                {
                    SiteProperties site = tenant.GetSitePropertiesByUrl("https://yoursite.sharepoint.com/sites/SiteA", false);
                    tenantContext.Load(site);
                    tenantContext.ExecuteQuery();
                    Console.WriteLine("Site is restored");
                }
                catch (ServerException e)
                {
                    Console.WriteLine("Cannot find the active site: " + e.Message);
                }
                Console.ReadLine();
            }
        }
    }
}

 

Below is the screenshot before running the above code. It shows the deleted site collection in the previous step in the Recycle Bin.

 

Below is the screenshot after the code to restore the site collection has been executed. You can see below that the recycle bin is empty and the restored site is available back in the site collection list.

Scenario 6 : Permanently delete a site collection

Above code snippets showed how to delete a site collection which can be restored from Recycle Bin. If you need to permanently delete a site collection from recycle bin make use of Tenant.RemoveDeletedSite method that permanently removes the deleted site collection from the recycle bin.

 

      using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.SharePoint.Client;
using System.Security;
using System.Threading;
namespace RemoveSiteCollectionFromRecycleBin
{
    class Program
    {
        static void  Main(string[] args)
        {
            using (ClientContext tenantContext = new ClientContext("https://yoursite-admin.sharepoint.com/"))
            {
                SecureString password = new  SecureString();
                foreach (char c in "yourpassword".ToCharArray())
                    password.AppendChar(c);
                tenantContext.Credentials = new  SharePointOnlineCredentials("admin@yoursite.onmicrosoft.com", password);
                var tenant = new  Tenant(tenantContext);
                SpoOperation spoOperation = tenant.RemoveDeletedSite("https://yoursite.sharepoint.com/sites/SiteA");
  
                tenantContext.Load(spoOperation);
                tenantContext.ExecuteQuery();
  
                Console.WriteLine("Time: " + DateTime.Now);
                while (!spoOperation.IsComplete)
                {
                    Thread.Sleep(3000);
                    tenantContext.Load(spoOperation);
                    tenantContext.ExecuteQuery();
                     
                }
                Console.WriteLine("Time: " + DateTime.Now);
                Console.WriteLine("Verify that site is removed");
                try
                {
                    SiteProperties site = tenant.GetSitePropertiesByUrl("https://yoursite.sharepoint.com/sites/siteA", false);
                    tenantContext.Load(site);
                    tenantContext.ExecuteQuery();
                    Console.WriteLine("Site is removed");
                }
                catch (ServerException e)
                {
                    Console.WriteLine("Cannot find the active site: " + e.Message);
                }
                Console.ReadLine();
            }
        }
    }
}

 


Conclusion

 

Hope this article gives you some insights on how to start with the basic operations around SharePoint Online using CSOM.
To conclude the basic steps that you need to follow

  1. Obtain ClientContext for the tenant admin site.
  2. Convert your password into SecureString format required to pass to the SharePointOnlineCredentials constructor.
  3. Pass credentials to the client context Credentials property using SharePointOnlineCredentials object.
  4. Create a tenant out of the client context.
  5. Call the relevant Tenant Method.

 


References

 

For further references have a look at the below links.

  1. Tenant Class
  2. CreateSite
  3. GetSiteByUrl
  4. GetSiteProperties
  5. GetSPOTenantWebTemplates
  6. RemoveDeletedSite
  7. RemoveSite
  8. RestoreDeletedSite
  9. SharePointOnlineCredentials
  10. SharePoint Server 2013 Client Components SDK
  11. SecureString
  12. Authentication with .NET Client Object Model

You can download the entire solution from the Technet Gallery at http://gallery.technet.microsoft.com/Perform-Basic-Operations-f00de858

See Also