1

Try to ignore some of the ugly if statements :D. I am very new to CSOM and caml. Is it possible to write Caml statement that returns the Folders in the Root of the document library only? Apologies if this is unclear! Happy Friday to all!

using (ClientContext clientContext = new ClientContext(webUri))
        {

            int rowLimit = 1;
            var camlQuery = new CamlQuery();
            camlQuery.ViewXml = @"<View Scope='RecursiveAll'><Query></Query><RowLimit Paged='TRUE'>" + rowLimit + "</RowLimit></View>";

            clientContext.Credentials = new SharePointOnlineCredentials(userName, password);
            ListItemCollectionPosition position = null;

            // This value is NOT List internal name
            List targetList = clientContext.Web.Lists.GetByTitle("Clients");

            //1st attempt
            //FolderCollection oFolderCollection = targetList.RootFolder.Folders;
            //clientContext.Load(oFolderCollection);
            //clientContext.ExecuteQuery();

            int clientCount = 0;
            do
            {
                ListItemCollection listItems = null;
                camlQuery.ListItemCollectionPosition = position;
                listItems = targetList.GetItems(camlQuery);
                clientContext.Load(listItems);
                clientContext.ExecuteQuery();
                position = listItems.ListItemCollectionPosition;
                items.AddRange(listItems.ToList());

                foreach (ListItem item in listItems)
                {
                    if (item != null && item.Folder != null)
                    {
                        try
                        {
                            clientContext.Load(item);
                            clientContext.Load(item.Folder);
                            clientContext.Load(item.Folder.ParentFolder);
                            clientContext.ExecuteQuery();
                            if ((item != null && item.Folder != null) && item.Folder.GetType() == typeof(Folder))
                            {
                                clientCount++;



                                //currently getting all files and folders, just want to start at top level folder then load in others if/as needed
                                Console.WriteLine(clientCount + "- Client: " + item.Folder.Name);
                                //clientFileDiver(item.Folder, clientContext);

                            }
                        }
                        catch (Microsoft.SharePoint.Client.ServerException)
                        {
                            if(item == null || item.Folder == null)
                            {
                                continue;
                            }
                            throw;
                        }
                        catch (ServerObjectNullReferenceException)
                        {
                            if (item == null || item.Folder == null)
                            {
                                continue;
                            }
                        }
                        catch (Exception)
                        {
                            throw;
                        }

                    }

                }

            }
            while (position != null);

EDIT: New Query I'm attempting but getting view threshold error again even with row limit

int rowLimit = 1;
string folderTypeId = "0x0120";
var camlQuery = new CamlQuery();
camlQuery.ViewXml = @"<View><Query><Where><BeginsWith><FieldRefName='ContentTypeId'/><Value Type = 'ContentTypeId'>" + folderTypeId + " </ Value ></BeginsWith></Where></Query><RowLimit Paged = 'TRUE'>" + rowLimit   + "</RowLimit></View>";

2 Answers 2

1

If you are interested to get only 'Folders', then use following in your CAML query:

<Where>
  <BeginsWith>
    <FieldRef Name="ContentTypeId" />
    <Value Type="ContentTypeId">0x0120</Value>
  </BeginsWith>
</Where>

SharePoint folder content type for folder starts with 0x0120. Check this Microsoft Document for details on content type ids.

You will need 'BeginsWith' since the actual content type id for Folders in your document library will be inherited and they will have the following format:

Parent Content Type ID + "00" + Hexadecimal GUID

Let me know if this helps.

2
  • This definitely helps and I'm looking into the docs you linked. I have added in your lines to my query which I needed to reformat since I am using a string but I think my formatting may have messed up the query. I get back a very generic ` Microsoft.SharePoint.Client.ServerException: 'Cannot complete this action. Please try again.' ` perhaps me changing the "ContentTypeId" to 'ContentTypeId'. Commented May 11, 2020 at 15:18
  • Another issue is this seems to only work with the RecursiveAll Scope tag. I am trying to only get the Folder in the root of the library, not all folders in the library. Commented May 11, 2020 at 18:12
0

Try changing this line:

camlQuery.ViewXml = @"<View Scope='RecursiveAll'><Query></Query><RowLimit Paged='TRUE'>" + rowLimit + "</RowLimit></View>";

to this

camlQuery.ViewXml = @"<View><Query></Query><RowLimit Paged='TRUE'>" + rowLimit + "</RowLimit></View>";

Remove the Scope='RecursiveAll' part from it. You can read more on View Scope property here.

1
  • So I was originally using that exact query but the issue is it's a large library and with how I'm currently requesting the items this seems to trigger the View Threshold limit error. The recursive all initially seemed to fix it until I got through a few hundred items and started seeing second-level folders in the mix. Commented May 11, 2020 at 13:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.