How to create folder structure in SDL Tridion 2011 SP1 using Core Service

The following is the code I use when I need to Get or Create Folders with SDL Tridion's CoreService. It's a simple recursive method that checks for the existence of the current folder. If it doesn't exist, it goes into GetOrCreate the parent folder and so on until it finds an existing path. On the way out of the recursion, it simply creates the new Folders relative to their immediate parent.

Note: this method does not check the input folderPath. Rather, it assumes it represents a valid path.

private FolderData GetOrCreateFolder(string folderPath, SessionAwareCoreServiceClient client)
{
    ReadOptions readOptions = new ReadOptions();

    if (client.IsExistingObject(folderPath))
    {
        return client.Read(folderPath, readOptions) as FolderData;
    }
    else
    {
        int lastSlashIdx = folderPath.LastIndexOf("/");
        string newFolder = folderPath.Substring(lastSlashIdx + 1);
        string parentFolder = folderPath.Substring(0, lastSlashIdx);
        FolderData parentFolderData = GetOrCreateFolder(parentFolder, client);
        FolderData newFolderData = client.GetDefaultData(ItemType.Folder, parentFolderData.Id) as FolderData;
        newFolderData.Title = newFolder;

        return client.Save(newFolderData, readOptions) as FolderData;
    }
}

I would use IsExistingObject - passing in the WebDAV URL - to see if the Folder already exists. If it returns false, you can go ahead and create the folder.

Edit: Here's some quick pseudo code...

string parentFolderId = @"/webdav/MyPublication/Building%20Blocks";

var client = GetCoreServiceClient();

if (!client.IsExistingObject(parentFolderId + "/AAA"))
{
   var folder = client.GetDefaultData(2, parentFolderId);
   folder.Title = "AAA";
   client.Save(folder);
   // Create the other folders and components here
}

This is what we used on one of our projects to create folders for a path.

static FolderData GetOrCreateFolder(List<string> folders, 
                                    FolderData root,
                                    SessionAwareCoreService2010Client client)
{
    var filter = new OrganizationalItemItemsFilterData();
    filter.ItemTypes = new [] { ItemType.Folder };

    var items = client.GetListXml(root.Id, filter).
                           Elements(TRIDION_NAMESPACE + "Item");

    foreach (var element in items)
    {
        if (folders.Count == 0)
        {
            break; // break from foreach
        }
        var titleAttribute = element.Attribute("Title");
        var idAttribute = element.Attribute("ID");
        if (titleAttribute != null && titleAttribute.Value == folders[0] && 
            idAttribute != null)
        {
            // folder exists
            FolderData fd = client.Read(idAttribute.Value, 
                                        EXPANDED_READ_OPTIONS) as FolderData;

            // We just took care of this guy, remove it to recurse
            folders.RemoveAt(0);

            return GetOrCreateFolder(folders, fd, client);
        }
    }

    if (folders.Count != 0)
    {
        //Folder doesn't exist, lets create it and return its folderdata
        var newfolder = new FolderData();
        newfolder.Title = folders[0];
        newfolder.LocationInfo = new LocationInfo { 
            OrganizationalItem = new LinkToOrganizationalItemData { 
                IdRef = root.Id 
            }
        };
        newfolder.Id = "tcm:0-0-0";

        var folder = client.Create(newfolder, EXPANDED_READ_OPTIONS) 
                               as FolderData;

        folders.RemoveAt(0);

        if (folders.Count > 0)
        {
            folder = GetOrCreateFolder(folders, folder, client);
        }
        return folder;
    }
    return root;
}

So you'd invoke it with something like this:

var root = client.Read("tcm:1-1-2", null) as FolderData;
var pathParts = "/ABCD/DEFG/aaaaa".Trim('/').Split('/').ToList();
var folder = GetOrCreateFolder(pathParts, root, client);

Tags:

C#

Tridion