2017-06-14 91 views
0

如何使用CSOM從特定的SharePoint library獲取所有子文件夾的列表?當用戶點擊「選擇文件夾」時,我想提供與SharePoint中相同的功能。使用CSOM從特定的SharePoint 2013庫獲取所有子文件夾

enter image description here

我發現這篇文章CAML and the Client Object Model,我認爲是相當不錯的,但我發現,當我嘗試了以下錯誤:

using (ClientContext clientContext = new ClientContext(this.SpSite)) 
{ 
    var web = clientContext.Web; 
    var list = web.Lists.GetByTitle('Contracts'); 

    var query = new CamlQuery(); 
    query.FolderServerRelativeUrl = "/Contracts"; 
    query.ViewXml = "<View Scope='RecursiveAll'>" 
    + "<Query>" 
    + " <Where>" 
    + "  <Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>1</Value></Eq>" 
    + " </Where>" 
    + "</Query>" 
    + "</View>"; 

    var folderItems = list.GetItems(query); 
    clientContext.Load(folderItems); 
    clientContext.ExecuteQuery(); 

    foreach (ListItem item in folderItems) 
    { 
     // item[ "..." ]; 
    } 
} 

我也嘗試了不同的CALM查詢但無濟於事:

query.ViewXml = "<View Scope=\"RecursiveAll\"> " + 
"<Query>" + 
"<Where>" + 
"<Eq>" + 
"<FieldRef Name=\"FileDirRef\" />" + 
"<Value Type=\"Text\">" + title + "</Value>" + 
"</Eq>" + 
"</Where>" + 
"</Query>" + 
"</View>"; 

任何幫助,將不勝感激。

謝謝。

UPDATE-1:

我發現問上StackExchange一個問題How to traverse SharePoint Library in Client Object Model?這是非常接近我所需要的,但仍然有它幾個問題:

  1. 它使用遞歸這意味着如果你有很多關卡,它最終會產生很多請求,並且可能會顯示非常慢。

  2. 返回的數據沒有排序。基於我提供的快照,而不是返回01,02,03等等......它以隨機順序返回值。

我希望,我將能夠使一個單一的電話,得到的所有文件夾和子文件夾列表,但我想這也可能最終耗費時間。

我想我有兩個選擇:

  1. 棒的遞歸方法,並找出如何理清數據,但我還需要弄清楚後者。

  2. 僅在最高級別請求文件夾,並且只有在展開文件夾時才請求子文件夾。理想情況下,如果使用這種方法,很高興知道文件夾是否有任何子文件夾,這意味着也必須弄清楚。

到達那裏但尚未完成。

所以,如果任何人都可以提供給我額外的反饋,片段,任何事情,請做。

謝謝。

回答

0

我建議可以一次裝載的所有文件夾的情況下,進行了以下調整:

var folderItems = list.GetItems(CamlQuery.CreateAllFoldersQuery()); 

由於CSOM API已經包含the built in method對於這個問題,加載所有文件夾項目可以這樣進行

其次,我建議從相關的列表項檢索文件夾對象:

var allFolders = folderItems.Select(i => i.Folder).ToList(); 

舉例:

public static List<Folder> GetAllFolders(List list) 
{ 
    var ctx = list.Context; 
    var folderItems = list.GetItems(CamlQuery.CreateAllFoldersQuery()); 
    ctx.Load(folderItems, icol => icol.Include(i => i.Folder)); 
    ctx.ExecuteQuery(); 
    var allFolders = folderItems.Select(i => i.Folder).ToList(); 
    return allFolders; 
} 

由於整個文件夾結構的負荷可能是從性能的角度看一個瓶頸,爲了避免你可能會考慮需求方法負載:

一旦加載窗體,檢索的級文件夾列表,並填充樹視圖:

var list = ctx.Web.Lists.GetByTitle(libraryTitle); 
var folders = FolderManager.GetFolders(list.RootFolder); 

var rootNode = new TreeNode(libraryTitle); 
folderSelector.Nodes.Add(rootNode); 
foreach (var folder in folders) 
{ 
     var folderNode = new TreeNode(folder.Name) {Tag = folder}; 
     rootNode.Nodes.Add(folderNode); 
} 

和然後按需加載的子文件夾,一旦expand事件被觸發填充節點:

private void folderTreeView_BeforeExpand(object sender, TreeViewCancelEventArgs e) 
{ 
    if (e.Node.Level > 0) //skip root level 
    { 
     var folders = FolderManager.GetFolders((Folder)e.Node.Tag); 
     foreach (var folder in folders) 
     { 
       var folderNode = new TreeNode(folder.Name) { Tag = folder }; 
       e.Node.Nodes.Add(folderNode); 
     } 
    } 
} 

其中

public static List<Folder> GetFolders(Folder parentFolder) 
{ 
    var ctx = parentFolder.Context; 
    var result = ctx.LoadQuery(parentFolder.Folders.Where(f => !f.ListItemAllFields.ServerObjectIsNull.Value)); 
    ctx.ExecuteQuery(); 
    return result.ToList(); 
} 
+0

感謝您抽出寶貴的時間來發布此。以後我會再次看到這一點,因爲按需加載肯定是一種方式,因爲我同意我使用的方法可能會在圖書館中存在大量文件夾的情況下創建瓶頸,但我只是在構建這是目前用於示範目的的原型,所以現在就可以做到這一點。 – Thierry

0

我結束了使用Caml Designer 2013計算出來。這個概念非常好,但對於我的口味來說仍然非常脆弱,使它變得無法使用,但經過無數次嘗試和錯誤之後,我最終查找了「查詢選項」部分。

原來,在這一節中,有一個選項可以處理子文件夾&,它最終爲我生成了正確的Calm查詢。

這是最後的結局:

using (ClientContext clientContext = new ClientContext(this.SpSite)) 
{ 
    List spList = clientContext.Web.Lists.GetByTitle(title); 
    clientContext.Load(spList); 
    clientContext.ExecuteQuery(); 

    if (spList != null && spList.ItemCount > 0) 
    { 
     CamlQuery camlQuery = new CamlQuery(); 
     camlQuery.ViewXml = 
      "<View Scope='RecursiveAll'>" 
      + " <Query>" 
      + " <Where>" 
      + "  <Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>1</Value></Eq>" 
      + " </Where>"        
      + " </Query>" 
      + " <ViewFields><FieldRef Name='Title' /></ViewFields>" 
      + "</View>"; 

      ListItemCollection listItems = spList.GetItems(camlQuery); 

      clientContext.Load(listItems); 
      clientContext.ExecuteQuery(); 

      foreach (var item in listItems) 
      { 
       Debug.WriteLine($"Title: {item.FieldValues["Title"]} 
       - FileRef: {item.FieldValues["FileRef"]} 
       - FileLeafRef: {item.FieldValues["FileLeafRef"]}"); 
      } 
     } 
    } 

上面的代碼產生以下結果:

Title: 2016 - FileRef: /Contracts/2016 - FileLeafRef: 2016 
Title: 2017 - FileRef: /Contracts/2017 - FileLeafRef: 2017 
Title: 01 - FileRef: /Contracts/2016/01 - FileLeafRef: 01 
Title: 02 - FileRef: /Contracts/2016/02 - FileLeafRef: 02 
Title: 03 - FileRef: /Contracts/2016/03 - FileLeafRef: 03 
Title: 04 - FileRef: /Contracts/2016/04 - FileLeafRef: 04 
Title: 05 - FileRef: /Contracts/2016/05 - FileLeafRef: 05 
Title: 06 - FileRef: /Contracts/2016/06 - FileLeafRef: 06 
Title: 07 - FileRef: /Contracts/2016/07 - FileLeafRef: 07 
Title: 08 - FileRef: /Contracts/2016/08 - FileLeafRef: 08 
Title: 09 - FileRef: /Contracts/2016/09 - FileLeafRef: 09 
Title: 10 - FileRef: /Contracts/2016/10 - FileLeafRef: 10 
Title: 11 - FileRef: /Contracts/2016/11 - FileLeafRef: 11 
Title: 12 - FileRef: /Contracts/2016/12 - FileLeafRef: 12 
Title: 01 - FileRef: /Contracts/2017/01 - FileLeafRef: 01 
Title: 02 - FileRef: /Contracts/2017/02 - FileLeafRef: 02 
Title: 03 - FileRef: /Contracts/2017/03 - FileLeafRef: 03 
Title: 04 - FileRef: /Contracts/2017/04 - FileLeafRef: 04 
Title: 05 - FileRef: /Contracts/2017/05 - FileLeafRef: 05 
Title: 06 - FileRef: /Contracts/2017/06 - FileLeafRef: 06 
Title: 07 - FileRef: /Contracts/2017/07 - FileLeafRef: 07 
Title: 08 - FileRef: /Contracts/2017/08 - FileLeafRef: 08 
Title: 09 - FileRef: /Contracts/2017/09 - FileLeafRef: 09 
Title: 10 - FileRef: /Contracts/2017/10 - FileLeafRef: 10 
Title: 11 - FileRef: /Contracts/2017/11 - FileLeafRef: 11 
Title: 12 - FileRef: /Contracts/2017/12 - FileLeafRef: 12 

所以,我做的,看看在返回什麼其他的屬性,所有剩下的FieldValues字典,看看是否有一個可以幫助我識別父節點或子節點,但即使已經存在,解析也很容易。

希望這會有所幫助,併爲您節省一些時間!

PS:我不知道你們有沒有注意到SharePoint專家,但我原來的問題代碼看起來與解決方案非常相似,但它沒有產生相同的結果。如果這是一個突出的亮點,請分享,因爲我很想知道,但不能再花費更多時間在這個問題上。

相關問題