Saturday, 5 August 2017

SharePoint 2013 – Retract Solution – Access Denied error

Hi All,

Today, new error and solution. I’ll explain the error which we received while retracting farm solution and the solution for it.

Background: We have SharePoint 2013 farm and were retracting solution, we were using chrome browser. In browser in two tabs our site was open and in one tab central admin. When we are trying to retract solution through central admin we were getting an “Access Denied” error. We are logged in with user having Administrator rights so it seems not to be user permission issue.
It was very small fix but thought to share, can save your time.

Error and Stack Trace:
Access denied.  Only machine administrators are allowed to create administration service job definitions of type: Microsoft.SharePoint.Administration.SPSolutionDeploymentJobDefinition, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c.
Application error when access /_admin/RetractSolution.aspx, Error=Access denied.  Only machine administrators are allowed to create administration service job definitions of type: Microsoft.SharePoint.Administration.SPSolutionDeploymentJobDefinition, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c.   at Microsoft.SharePoint.Administration.SPAdministrationServiceJobDefinition..ctor(String name, SPService service, SPServer server, SPJobLockType lockType)     at Microsoft.SharePoint.Administration.SPSolutionDeploymentJobDefinition..ctor(String solutionName, Guid solutionId, UInt32 lcid, SPTimerService service, SPCompatibilityRange compatibilityRange)     at Microsoft.SharePoint.Administration.SPSolutionLanguagePack.CreateSolutionDeployTimerJob(DateTime...              e4a5099e-e182-6064-8575-d8b087e7d93c
General                             8nca      Medium             ... dt, Collection`1 webApplications, SPSolutionDeploymentJobType jobType, Boolean globalInstallDlls, Boolean force, Boolean isRestore, SPCompatibilityRange compatibilityRange)     at Microsoft.SharePoint.ApplicationPages.SolutionPageBase.CreateDeploymentJob(Boolean deploy, String strSelectedWeb, Boolean globalInstall, DateTime dt, Boolean localDeployment)     at Microsoft.SharePoint.ApplicationPages.RetractSolutionPage.BtnSubmit_Click(Object sender, EventArgs e)     at System.Web.UI.WebControls.Button.OnClick(EventArgs e)     at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)     at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)     at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsy...              e4a5099e-e182-6064-8575-d8b087e7d93c

Solution:

It seems to be weird error. No user permission issue.

We googled a lot and then got below article related to same issue but not exact one.


In above article not exact issue mentioned but at least we got an idea. We have closed the browser, open the central admin again with run as administrator option, tried again it worked like charm.

Thanks!

Enjoy Reading J

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

Thursday, 27 July 2017

SharePoint Online / Office 365 - Exporting All the Terms from Particular TermSet in .CSV file using CSOM and console application

Hi All,

In this article I’ll explain how to export term sets in .CSV file using CSOM and console application.  


There are multiple approaches to export the terms from given TermSet either using PowerShell + CSOM or using CSOM in console application. In one of my previous article "SharePointOnline / Office 365 : Exporting All The Terms From Particular TermSet In .csvfile Using CSOM & PowerShell" I explained how to export the TermSet using CSOM + PowerShell. 

In this article I’ll go through step by step for exporting TermSet using CSOM in console application.

There is no as such difference in both the approaches but if we want to make it more configurable (like configuration in .config file, for ex. – TermStore name or specific TermSet name etc. ) then Console Application approach is preferable.

I have my trial Office 365 account and term store manager page looks like, created three terms (IT, HR and Finance) in OOB term set “Department” under “People” group:

So in our console application we will export the above three terms created under “Department” term set in “People” group in default term store (since there only one termstore).

Step 1: Get the required details from config file (App.config) and connecting to Office 365:

In last article “Office365 / SharePoint Online - Connecting Office 365 / SharePoint Online Site UsingCSOM (Client Object Model)” I have given detailed steps to connect Office 365 through CSOM and Console Application. Please have a look once. Following is the code snippet for this step:

       #region Site Details - Read the details from config file
            string siteURL = ConfigurationManager.AppSettings["siteURL"];
            string userName = ConfigurationManager.AppSettings["userName"];
            string password = ConfigurationManager.AppSettings["password"];
            //Path where we need to create the .CSV file
            string csvFilePath = ConfigurationManager.AppSettings["csvfilepath"];
       #endregion

#region Connect To O365

            //Create the client context object and set the credentials
//Create the client context object and set the credentials
              ClientContext clientContext = new ClientContext(siteURL);
       SecureString securePassword = new SecureString();

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

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

Step 3: Get the Terms from respective TermSet : To read the Terms from respective TermSet we need to get the reference for following objects

1.       TaxonomySession : This object is the initial point for all taxonomy operations. Get reference to the TaxonomySession object as

TaxonomySession taxonomysession = TaxonomySession.GetTaxonomySession(clientContext);

2.       TermStore : Get reference to default TermStore object. Once we have TaxonomySession class, we will get the default term store as  

TermStore termStore = taxonomysession.GetDefaultSiteCollectionTermStore();

3.       TermGroupCollection : We will fetch all the groups (TermGroupCollection) from TermStore object as
                TermGroupCollection groupCollection = termStore.Groups;
                clientContext.Load(groupCollection);
                clientContext.ExecuteQuery();

4.       TermGroup : Then get the reference to the TermGroup object in which our TermSet is created, here we are fetching the terms from the term set which is created under group “People” as

TermGroup termGroup = groupCollection.GetByName("People");
clientContext.Load(termGroup);
clientContext.ExecuteQuery();

5.       TermSet : From termGroup object we will read our “Department” term set as

TermSet termSet = termGroup.TermSets.GetByName("Department");
clientContext.Load(termSet);
clientContext.ExecuteQuery();

6.       TermCollection : We have our term set ready, get all terms in it using TermCollection object as

TermCollection departmentTerms = termSet.Terms;
                       clientContext.Load(departmentTerms);
                       clientContext.ExecuteQuery();

Step 4: Write terms to .CSV file : Since now we have all “Department” terms, we will write them to .CSV file.  To write into .CSV file we will need array of string and we will use Syste.IO.File object as
ArrayList termsArrayList = new ArrayList(departmentTerms.Count);

              foreach (Term term in departmentTerms)
              {
                 termsArrayList.Add(term.Name);
              }

                             //Writing to .CSV file as path specified in .config file.
System.IO.File.WriteAllLines(csvFilePath,           (string[])termsArrayList.ToArray(typeof(string)));


Complete Code:

using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.Taxonomy;
using System;
using System.Collections;
using System.Configuration;
using System.Security;

namespace CSOM_ExportTermSets
{
    class Program
    {
        static void Main(string[] args)
        {
            #region Site Details - Read the details from config file
            string siteURL = ConfigurationManager.AppSettings["siteURL"];
            string userName = ConfigurationManager.AppSettings["userName"];
            string password = ConfigurationManager.AppSettings["password"];
            //Path where we need to create the .CSV file
            string csvFilePath = ConfigurationManager.AppSettings["csvfilepath"];
            #endregion

            #region ConnectTo O365

            //Create the client context object and set the credentials
            ClientContext clientContext = new ClientContext(siteURL);
            SecureString securePassword = new SecureString();

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

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

            #endregion

            #region Get the Terms

TaxonomySession taxonomysession = TaxonomySession.GetTaxonomySession(clientContext);
    
            if (taxonomysession != null)
            {
 TermStore termStore = taxonomysession.GetDefaultSiteCollectionTermStore();
                if (termStore != null)
                {
                    TermGroupCollection groupCollection = termStore.Groups;
                    clientContext.Load(groupCollection);
                    clientContext.ExecuteQuery();

                    TermGroup termGroup = groupCollection.GetByName("People");
                    TermSet termSet = termGroup.TermSets.GetByName("Department");

                    clientContext.Load(termGroup);
                    clientContext.Load(termSet);
                    clientContext.ExecuteQuery();

                    TermCollection departmentTerms = termSet.Terms;
                    clientContext.Load(departmentTerms);
                    clientContext.ExecuteQuery();

                    ArrayList termsArrayList = new ArrayList(departmentTerms.Count);

                    foreach (Term term in departmentTerms)
                    {
                        termsArrayList.Add(term.Name);
                    }

                    //Writting to .CSV file as path specified in .config file.
System.IO.File.WriteAllLines(csvFilePath, (string[])termsArrayList.ToArray(typeof(string)));

Console.WriteLine("Terms are written in .CSV file. Please hit the any key to exit the console");
                    Console.ReadKey();
                }//if (termStore != null)
            }//if (taxonomysession != null)
            #endregion
        }//main
    }//cs
}//ns

Thanks!

Enjoy Reading :)

As usual any feedback / query / suggestions are most welcome!!!

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 :)