zaitsman
zaitsman

Reputation: 9519

Filtering out hidden and system sharepoint folders on windows phone 7

I am working with sharepoint site using classes in the Microsoft.Sharepoint.Client namespace. As i am working on Windows Phone 7, i can not find the SPFolderCollection/SPFolder classes.

I need to filter out hidden folders and system folders (e.g._vti_pvt).

I found an example as follows:

// filter the folders like “_catalogs” or “_private”
                if (folder.ParentListId != Guid.Empty)
                {
                    SPList list  = web.Lists[folder.ParentListId];
//filter the folders like “Reporting Templates” or “IWConvertdForms”
                    if (list.Hidden == false)

(The example taken from http://go4answers.webhost4life.com/Example/know-spfolder-invisible-visible-27871.aspx).

However, as i have no 'SP' classes, i can't implement it on Windows Phone (no ParentListId method).

Any ideas/workarounds would be much appreciated.

Thank you.

P.S. Please note, i would like to avoid using CAML at all costs; i only need to be able to list and retrieve urls of files and folders, i do not need to work with lists or notifications.

UPDATE So it seems i can circumvent the limitation as follows:

Foldercollection folder_assist = new FolderCollection( WHAT DO I PUT HERE??? );
    ctx.Load(folders);
                ctx.ExecuteQueryAsync(delegate(object sender1, ClientRequestSucceededEventArgs args)
                {
                foreach (Folder f in folders)
                {
                    ctx.Load(f.ParentFolder);
                }
                ctx.ExecuteQuery();
                foreach (Folder f in folders)
                {
                    List ejh;
                     // if we are in the top folder, the .parentfolder may be null
                    if (f.ParentFolder != null && f.ParentFolder.Name != "")
                    {
                        ejh = ctx.Web.Lists.GetByTitle(f.ParentFolder.Name);
                    }
                    else
                    {
                        ejh = ctx.Web.Lists.GetByTitle(f.Name);
                    }
                    ctx.Load(ejh);

                    try
                    {
                        ctx.ExecuteQuery();
                    }
                    catch
                    {
                        ejh = null;
                    }
                    if (ejh != null)
                    {
                        if (ejh.Id != Guid.Empty)
                        {
                            if (ejh.Hidden == false)
                            {
                     folder_assist.Add(f.ServerRelativeURL;
                         }
                        }
                    }
                } 
                win.Dispatcher.BeginInvoke((Action)(() => DO SOME WORK...

            }, delegate(object sender1, ClientRequestFailedEventArgs args)
                {
                   win.Dispatcher.BeginInvoke((Action)(() => MessageBox.Show("something went wrong" + args.ToString())));
                });

The problem i am experiencing now is with the firstline - it seems Microsoft.Sharepoint.FolderCollection constructor requires the context (which i have and can pass easy) and the ObjectPath type, which i don't have since i just need a placeholder to collect all of the folders that are not hidden and not special.

How do i work around this?

Update 2

Okay, pretty obvious outcome, i just used List<Folder> for fassist.

However, there are two more things that i noticed:

a) the performance of my solution is rather appalling. Where it took moments to get a list before (when i wasn't filtering in the async thread), it now takes a significant 10-20 seconds to get the list (and i only have a handful of items on the server!).

Any ideas/suggestions? (the real problem is i cant just pass folders collection back to UI thread to parse and add one by one as i would still need to executequery for the parentFolder. And if i try to do that in async while in the foreach() loop in the UI thread, i get a noninstantiated object as the UI thread does not wait for the execution of the query. If i make it wait using the AutoResetEvent, the UI thread just becomes locked. And WP7 does not allow to use ClientContext.Executequery() in the UI thread. Bummer.)

b) I seem to still have the 'Forms' folders within every folder i access! Working on that right now, but any ideas would be much appreciated.

Upvotes: 2

Views: 4190

Answers (2)

Vadim Gremyachev
Vadim Gremyachev

Reputation: 59358

How to exclude "system" folders using SharePoint CSOM

Option 1

Folder class exposes Folder.ListItemAllFields property that specifies the list item associated with the folder, for "system" folders the corresponding list item does not exist.

The following example demonstrates how to load folders and verify whether the folder is regular or "system" folder:

using (var ctx = new ClientContext(webUri))
{

      var list = ctx.Web.Lists.GetByTitle(listTitle);
      var folder = list.RootFolder;
      ctx.Load(folder);
      ctx.Load(folder.Folders, fcol => fcol.Include(f => f.Name, f => f.ServerRelativeUrl, f => f.ListItemAllFields));
      ctx.ExecuteQuery();
      foreach (var subFolder in folder.Folders)
      {
           bool systemFolder = subFolder.ListItemAllFields.ServerObjectIsNull != null && subFolder.ListItemAllFields.ServerObjectIsNull.Value;
           if(!systemFolder)
              //Process regular Folder...
      }
 }

Option 2

Below is demonstrates an alternative way of loading folders using CAML query via SharePoint CSOM

using (var ctx = new ClientContext(webUri))
{

    var list = ctx.Web.Lists.GetByTitle(listTitle);
    var items = list.GetItems(CamlQuery.CreateAllFoldersQuery());
    ctx.Load(items,icol => icol.Include(i => i.Folder));
    ctx.ExecuteQuery();
    var folders = items.Select(i => i.Folder);
    foreach (var folder in folders)
    {
        //Process folder...
    }
}

Key points:

  • The advantage of this approach that only regular folders will be returned

Upvotes: 2

Adam Carr
Adam Carr

Reputation: 688

The reason the classes don't have SP in front of them is example you have used is the Server Object Model, this only runs on a server with SharePoint installed.

The version on the Windows Phone you are using is the Client Object Model and this does not have the SP prefixes on all of the classes.

Ideally to answer the question I would need to know where are you getting the reference to the folders? Site, Web a list? or why are you trying to enumerate the folders?

A FolderCollection has to come from an object somewhere in the client object model.

e.g. ctx.Web.Folders will return a FolderCollection that you can enumerate, rather than just creating a new FolderCollection.

Most higher level objects like Web and List usually have a .Folders property you can retrieve a list of folders from without using CAML.

You could try using this code.

        ClientContext ctx = new ClientContext("http://yoururl");

        var webFolders = ctx.Web.Folders;
        ctx.Load(webFolders);
        ctx.Load(ctx.Web.Folders, folders => folders.Include(folder => folder.ParentFolder));
        ctx.Load(ctx.Web.Folders, folders => folders.Include(folder => folder.Folders));

        ctx.ExecuteQuery();
        foreach (var folder in webFolders)
        {
           // Do stuff here!
        }

It will load all folders from the Web (effectively the root folder) and their parents and children. I am still lost on how you can hide the folders though in an efficient way.

See my comments as for why I think the code is running slowly.

EDIT:

You could try this to get all Document Libraries in a Web.

        var webLists = ctx.Web.Lists;
        ctx.Load(webLists);

        // request that List.RootFolder is returned
        ctx.Load(ctx.Web.Lists, lists => lists.Include(list => list.RootFolder ));
        // request that RootFolder.Folders is returned
        ctx.Load(ctx.Web.Lists, lists => lists.Include(list => list.RootFolder.Folders ));
        // only return lists with a BaseType of 101 (Document Library)
        ctx.Load(ctx.Web.Lists, lists => lists.Where(list => list.BaseTemplate == 101));

        ctx.ExecuteQuery();
        foreach (var list in webLists)
        {
            var rootFolder = list.RootFolder;
            // Do stuff here!
        }

Upvotes: 0

Related Questions