Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CAML query that includes folders in result set

I'm trying to write a CAML query that executes against a specific SPList, scoped to a specific folder, recursive from that point, and returns all ListItems (which meet a criteria) and Folders.

Here's the code for the query which seems like it should work (formatted for readability):

SPQuery query = new SPQuery();
query.Query = "
<Where>
    <Or>
        <Contains>
            <FieldRef Name=\"FileRef\" />
            <Value Type=\"Text\">foo</Value>
        </Contains>
        <Eq>
            <FieldRef Name=\"FSObjType\" />
            <Value Type=\"Lookup\">1</Value>
        </Eq>
    </Or>
</Where>";

query.ViewFields = "
<FieldRef Name=\"CustomField1\" Nullable=\"TRUE\" />
<FieldRef Name=\"CustomField2\" Nullable=\"TRUE\" />
<FieldRef Name=\"CustomField3\" Nullable=\"TRUE\" />
";

query.RowLimit = 500;
query.ViewAttributes = "Scope=\"RecursiveAll\"";
query.Folder = startingFolder;
DataTable dt = myList.GetItems(query).GetDataTable();

So - this only returns the ListItems - no folders.

If I remove the other conditions from the query, only leaving the FSObjType=1, I get a COM exception "Cannot complete this action. Please try again."

If I then remove the ViewFields, leaving only the Scope=RecursiveAll and FSObjType=1, I get an empty result set back.

like image 847
Rex M Avatar asked Oct 13 '09 00:10

Rex M


2 Answers

Everyone is close, but not quite right.

using (SPSite site = new SPSite("http://server/site"))
{
  SPWeb web = site.RootWeb; // See disposal guidance http://blogs.msdn.com/b/rogerla/archive/2008/10/04/updated-spsite-rootweb-dispose-guidance.aspx

  SPQuery query = new SPQuery();
  query.Query = @"
          <Where>
            <BeginsWith>
              <FieldRef Name='ContentTypeId' />
              <Value Type='ContentTypeId'>0x0120</Value>
            </BeginsWith>
          </Where>";
  query.ViewAttributes = "Scope='RecursiveAll'";
  SPList list = web.Lists[listId];
  SPListItemCollection items = list.GetItems(query);
  // Do stuff with your folders
}

First of all, using this FieldRef is wrong:

<FieldRef Name='ContentType' /><Value Type='Text'>Folder</Value>

because the folder content type can be inherited. Therefore, you need to compare against the content type ID, like this:

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

And then, set the view attribute Scope to RecursiveAll

<View Scope='RecursiveAll'>...</View>

That should return any item whose content type inherits from Folder (0x0120)

like image 200
Dave T. Avatar answered Oct 29 '22 22:10

Dave T.


I don't have my dev image to test against, so I might need to revise this later; but I think you could try

query.ViewAttributes = "Scope=\"Recursive\""; 

Retrieving the items will allow you to use SPUtility.GetUrlDirectory(url) to get the folder path for a given item, and parse the folder hierarchy from there.

like image 30
gn22 Avatar answered Oct 29 '22 21:10

gn22