Monday, March 15, 2010

SharePoint 2010: Manage (Create/Delete/Rename) list folders with Client Object Model (OM)

SharePoint 2010 Client Object models allows almost everything to do from client side with Client OM. In this post I’ll show how to Add, remove and rename SharePoint list folders with Client OM. I have been using Managed client OM. However you can get the idea of how to use this code from Client OM for silverlight and Client OM for ECMAScript. Also the code snippet I have posted here in this post is will only work for list folders. However by changing few parts you can make it working for library.

Create or Add Folder

The following code snippet shows how to add a new folder in a list.

public void CreateFolder(string siteUrl, string listName, string relativePath, string folderName)
{
using (ClientContext clientContext = new ClientContext(siteUrl))
{
Web web = clientContext.Web;
List list = web.Lists.GetByTitle(listName);

ListItemCreationInformation newItem = new ListItemCreationInformation();
newItem.UnderlyingObjectType = FileSystemObjectType.Folder;
newItem.FolderUrl = siteUrl + "/lists/" + listName;
if (!relativePath.Equals(string.Empty))
{
newItem.FolderUrl += "/" + relativePath;
}
newItem.LeafName = folderName;
ListItem item = list.AddItem(newItem);
item.Update();
clientContext.ExecuteQuery();
}
}

As shown in the code snippet above, to add a folder with Client OM you need to create an instance of ListItemCreationInformation and set it’s UnderlyingObjectType to Folder. You can also set the path where to create the folder by setting the FolderUrl property value.

You can call the CreateFolder method as shown below which will create a folder ‘myfolder’ in the list ‘mylist’. As relative path is passed empty, the folder will be added in the root folder of the list.

helper.CreateFolder("http://server", "mylist", "", "myfolder");

However you can add folder in any subfolder of the list. For example the following code snippet will add the folder ‘mysubfolder’ in the list ‘mylist’ under the folder ‘myfolder’.

helper.CreateFolder("http://server", "mylist", "myfolder", "mysubfolder");

 

Delete or Remove folder

To delete folder with Client OM, you need to query the folder first. You can do so by using instantiate a CamlQuery object and executing it. The following code snippet shows how to delete folder.

public void DeleteFolder(string siteUrl, string listName, string relativePath, string folderName)
{
    using (ClientContext clientContext = new ClientContext(siteUrl))
    {
        Web web = clientContext.Web;
        List list = web.Lists.GetByTitle(listName);

        CamlQuery query = new CamlQuery();
        query.ViewXml = "<View Scope=\"RecursiveAll\"> " +
                        "<Query>" +
                            "<Where>" +
                                "<And>" +
                                    "<Eq>" +
                                        "<FieldRef Name=\"FSObjType\" />" +
                                        "<Value Type=\"Integer\">1</Value>" +
                                     "</Eq>" +
                                      "<Eq>" +
                                        "<FieldRef Name=\"Title\"/>" +
                                        "<Value Type=\"Text\">" + folderName + "</Value>" +
                                      "</Eq>" +
                                "</And>" +
                             "</Where>" +
                        "</Query>" +
                        "</View>";

        if (relativePath.Equals(string.Empty))
        {
            query.FolderServerRelativeUrl = "/lists/" + listName;
        }
        else
        {
            query.FolderServerRelativeUrl = "/lists/" + listName + "/" + relativePath;
        }

        var folders = list.GetItems(query);

        clientContext.Load(list);
        clientContext.Load(folders);
        clientContext.ExecuteQuery();
        if (folders.Count == 1)
        {
            folders[0].DeleteObject();
            clientContext.ExecuteQuery();
        }
    }
}

As shown in the above code snippet, I first instantiated the CamlQuery with the query to search the folder. The only trick to search folder only is to use the following part in the CAML query. If you want to use files only then use value 0 instead of 1.

<FieldRef Name="FSObjType" />
<Value Type="Integer">1</Value>

However you can use “CamlQuery.CreateAllFoldersQuery()” to get the query to search all folders. After preparing the CAML query you need to execute this against the list. For optimization you can specify the field names you want to load inside the Load method.

Rename Folder

To rename folder you need to get the folder item first. To get the folder you need to query the list for folder as shown in section “Delete or Remove Folder”. The following code snippet shows how to rename folder.

public void RenameFolder(string siteUrl, string listName, string relativePath, string folderName,string folderNewName)
{
    using (ClientContext clientContext = new ClientContext(siteUrl))
    {
        Web web = clientContext.Web;
        List list = web.Lists.GetByTitle(listName);

        string FolderFullPath = GetFullPath(listName, relativePath, folderName);

        CamlQuery query = new CamlQuery();
        query.ViewXml = "<View Scope=\"RecursiveAll\"> " +
                        "<Query>" +
                            "<Where>" +
                                "<And>" +
                                    "<Eq>" +
                                        "<FieldRef Name=\"FSObjType\" />" +
                                        "<Value Type=\"Integer\">1</Value>" +
                                     "</Eq>" +
                                      "<Eq>" +
                                        "<FieldRef Name=\"Title\"/>" +
                                        "<Value Type=\"Text\">" + folderName + "</Value>" +
                                      "</Eq>" +
                                "</And>" +
                             "</Where>" +
                        "</Query>" +
                        "</View>";

        if (relativePath.Equals(string.Empty))
        {
            query.FolderServerRelativeUrl = "/lists/" + listName;
        }
        else
        {
            query.FolderServerRelativeUrl = "/lists/" + listName + "/" + relativePath;
        }
        var folders = list.GetItems(query);

        clientContext.Load(list);
        clientContext.Load(list.Fields);
        clientContext.Load(folders, fs => fs.Include(fi => fi["Title"],
            fi => fi["DisplayName"],
            fi => fi["FileLeafRef"]));
        clientContext.ExecuteQuery();

        if (folders.Count == 1)
        {

            folders[0]["Title"] = folderNewName;
            folders[0]["FileLeafRef"] = folderNewName;
            folders[0].Update();
            clientContext.ExecuteQuery();
        }
    }
}

As shown in the code snippet above, I have specified the field names (Title, DisplayName, FileLeafRef) in the load method to ensure that these fields are populated on the client side. Once the query is executed by invoking the ClientContext.ExecuteQuery, the folders are populated. To rename folder you need to modify at least two properties (Title, FileLeafRef). Finally you need to call the update method and to send the change back to the server need to invoke the ExecuteQuery method

Search Folder

You can enumerate a list for folders as shown below:

public void SearchFolder(string siteUrl, string listName, string relativePath)
{
    using (ClientContext clientContext = new ClientContext(siteUrl))
    {
        Web web = clientContext.Web;
        List list = web.Lists.GetByTitle(listName);

        string FolderFullPath = null;

        CamlQuery query = CamlQuery.CreateAllFoldersQuery();

        if (relativePath.Equals(string.Empty))
        {
            FolderFullPath = "/lists/" + listName;
        }
        else
        {
            FolderFullPath = "/lists/" + listName + "/" + relativePath;
        }
        if (!string.IsNullOrEmpty(FolderFullPath))
        {
            query.FolderServerRelativeUrl = FolderFullPath;
        }
        IList<Folder> folderResult = new List<Folder>();

        var listItems = list.GetItems(query);

        clientContext.Load(list);
        clientContext.Load(listItems, litems => litems.Include(
            li => li["DisplayName"],
            li => li["Id"]
            ));

        clientContext.ExecuteQuery();

        foreach (var item in listItems)
        {

            Console.WriteLine("{0}----------{1}", item.Id, item.DisplayName);
        }
    }
}

As shown above, the CamlQuery.CreateAllFoldersQuery method generate a query which will query folders. You can pass that query in any list’s GetItems method to get the folders of that list. You can also specify the root folder from which to start searching for folder by specifying the CamlQuery.FolderServerRelativeUrl property.

 

Conclusion

Client OM has opened a new window on SharePoint programming. I have found it very useful as it exposed almost full power of SharePoint on client side.

31 comments:

  1. Great article!

    Do you know how I can get reference to Folder object from ListItem object if I am traversing a document library using managed client object model?

    ReplyDelete
  2. Hi,
    To get the folder object with client object model all you need to know the folder relative path or id. For list the relative path starts with '/lists/listname'. For document library the path is something like '/document library/'. For searching library folder you need to know the relative path and you can get the path by opening the site in SharePoint designer. Then create a caml query for searching folder by calling CamlQuery.CreateAllFoldersQuery(). Finally set the relative path of the query of this caml.

    ReplyDelete
  3. Thanks for your reply.

    I only have folder's id and not relative path. How can I get the items inside folder based on it's id?

    ReplyDelete
  4. call 'list.GetItemById()' instead of 'list.getitems()' as shown in the post. Passing the id will return the folder with that id.

    ReplyDelete
  5. Thanks. I realized that I did not "include" displayname while retrieving listitems and that was the reason why I wanted to get reference to folder from list item. Now I can use listitem itself.

    But my other question is how can I get listitems inside a folder?

    ReplyDelete
  6. Use the CamlQuery object and set the query's FolderServerRelativeUrl property to the path from which to start searching items. You can even control the inner folder search by setting the Scope property of caml.

    ReplyDelete
  7. Hi Sohel,
    Thanks for the useful post...

    can u clarify the below ...

    How to Add items within a folder created....using ECMA script??

    ReplyDelete
  8. no problm i figured it out anyways thnks for the useful post :)

    ReplyDelete
  9. I have a custom list called 'My List' with three custom fields, 'Document Library Name', 'Last Accessed Date' and 'Secure'.

    How to read these fields through ECMAscript ? I am able to retrieve the field 'Secure' but not others. Looks like Field names with multiple words (because of spaces) cannot be accessed straight forward. I would greatly appreciate any help.

    get_item('Secure') works great. But get_item('Document Library Name') does not work.

    ReplyDelete
  10. I renamed the columns to without spaces. But I have another issue.

    'DocumentLibraryName' is a hyperlink column.

    I am able to retrieve the field 'LastAccessedDate' but not 'DocumentLibraryName'. When I try to access 'DocumentLibraryName', I get [object,object]. How to retriev hyperlink title and hyperlink url value ?

    ReplyDelete
  11. When you have got [object,object] it means sever has returned you some value but the value is not simple data type (like int,datetime etc). You can use Visual Studio debugger or firefox to find out what the object is and then u can access properties. Linked title may be not only title but a complex object with like and tile property.

    ReplyDelete
  12. Hi sohel
    i am getting "File not found error"
    following is my code

    ClientContext _ctx = new ClientContext("http://:/");
    Web _web = _ctx.Web;
    _ctx.Load(_web);
    _ctx.ExecuteQuery();
    CreateFolder(_ctx.Url, "Docket Filings", "", "Test1");

    ReplyDelete
  13. Santosh,
    You need to pass the url of the web in clientcontext to make it working. So if your site url is http://myserver and your web name is myweb then the url in client context will be http://myserver/myweb. When you'll call for clientContext.Web, it'll return the myweb for the above url.

    ReplyDelete
  14. Hi all,

    How can you rename a folder or a file using ecma script only?

    ReplyDelete
  15. In my post 'http://ranaictiu-technicalblog.blogspot.com/search/label/Client%20OM' you'll find how to use Ecmascript to manipulate list items. First try to get the folder from ecmascript as shown in the link. Then apply the functionality shown in the rename section of the current post.

    ReplyDelete
  16. Thanks... that was some useful information for me..

    I tried manipulating the file name and folder name using 'LinkFilename' as a key to rename the file/folder ...it shows a request failed error..
    0x80070057
    The field that you are trying to update may be read only.

    ReplyDelete
  17. Hi,

    You need to get the list item and then get the file by accessing listItem.File. Then move the file by using listItem.file.moveTo method. You can get the class reference from http://msdn.microsoft.com/en-us/library/ee550751.aspx

    I'll try to write a post in future on renaming file/folder using EcmaScript.

    ReplyDelete
  18. HI..
    Im doing an add in for outlook 2010 for attachments,
    I have to move attachments to sharepoint site.
    Is it possible to show a folder dialog box for users so that he can select one of the folder or list to save those files? creating folders n deleting floders also required,
    presently. Im displaying those things in a treeview. for creating n deleting i have provided bottons to do.. i think its not a good way to do it.
    any other way for to browse those folders n document libraries??

    ReplyDelete
  19. Yes can use CAML queries to get folders of a document library. You can google with topic 'sharepoint caml query get folder' to get caml query to find folders. Run the CAML query first using the approach shown in the method SearchFolder method.

    ReplyDelete
  20. not possible to rename the files in the document libraries? how can i do that?

    ReplyDelete
  21. Hi Sohel, to save file.
    using (ClientContext ctx = new ClientContext(siteURL))
    {
    Web web = ctx.Web;
    List list = ctx.Web.Lists.GetByTitle(GetListName(treeView1.SelectedNode));
    ListItemCreationInformation newItem = new ListItemCreationInformation();
    newItem.UnderlyingObjectType = FileSystemObjectType.File;
    newItem.LeafName = fci.Url;
    newItem.FolderUrl = treeView1.SelectedNode.Name;
    ListItem listitem = list.AddItem(newItem);
    listitem.Update();
    ctx.ExecuteQuery();

    }

    but while ctx.ExecuteQuery() it throws an error "To add an item to a document library, use SPFileCollection.Add()" hw can i do it thru COM?

    ReplyDelete
  22. To upload file please follow my post: http://ranaictiu-technicalblog.blogspot.com/2010/06/sharepoint-2010-attach-files-to.html

    ReplyDelete
  23. while creating folders in customizing report and site collection reports getting error like this
    "The file or folder name contains characters that are not permitted. Please use a different name." any solutions?

    ReplyDelete
  24. helper.CreateFolder("http://server", "mylist", "", "myfolder");

    What is the "helper.CreateFolder"

    I need to create 64000 folder Programmatically in a Document Lib. using the Clent object modal.

    can u please help me, how i will do this.
    I am try ur code but I am not figure out what is "helper.CreateFolder"
    My code :

    string listName = "Orange Files Sample 1";
    string folderName = "Caley R. Dallway";
    string relativePath = "UNV Components Design.docx";
    string siteUrl = "http://sp2010unv:8085/volunteer/volunteerMgt";


    ClientContext clientContext = new ClientContext(siteUrl);
    Web web = clientContext.Web; List list = web.Lists.GetByTitle(listName);

    ListItemCreationInformation newItem = new ListItemCreationInformation();
    newItem.UnderlyingObjectType = FileSystemObjectType.Folder;
    newItem.FolderUrl = siteUrl + "/" + "folderName" + listName;

    if (!relativePath.Equals(string.Empty))
    {
    newItem.FolderUrl += "/" + relativePath;
    }
    newItem.LeafName = folderName;
    ListItem item = list.AddItem(newItem);
    item.Update();
    clientContext.ExecuteQuery();

    ReplyDelete
  25. does your filename has any special characters? Please check if the name or filename url is ok

    ReplyDelete
  26. how to query folders or files inside subfolder?

    ReplyDelete
  27. Use code like
    query.FolderServerRelativeUrl = "/lists/listName/subfolder";

    ReplyDelete
  28. Hello

    I want to craete a folder inside a folder in document library.I am able to create the root folder.but not able to create sub folder.

    code is
    ClientContext clientContext = new ClientContext("http://intranet.contoso.com/sites/Lab01A");
    Web web = clientContext.Web;
    List list = web.Lists.GetByTitle("Shared Documents");

    ListItemCreationInformation newItem = new ListItemCreationInformation();
    newItem.UnderlyingObjectType = FileSystemObjectType.Folder;

    newItem.FolderUrl = foldername;
    newItem.LeafName = fldName;
    ListItem item = list.AddItem(newItem); item.Update();
    clientContext.ExecuteQuery();
    Console.WriteLine(parts[b]);
    Error:

    The file or folder name contains characters that are not permit....
    please help me out

    ReplyDelete
    Replies
    1. I encounter same issue, unable to create subfolder, the error is:

      Invalid file name.

      The file name you specified could not be used. It may be the name of an existing file or directory, or you may not have permission to access the file.

      Delete
  29. Please provide the code for Renaming the folder using java
    (I triedthrough dws.updatedwsData())
    But I am unable to find the CAML query for renaming the folder....Please help us...

    ReplyDelete