7

When building an ECL Provider we are trying to have nested folders (a folder within a folder, just like on a file system). We have implemented a GetFolderContent method and this is firing when we click on the first level folder within the mount point - our items are showing up in the CME and one of those items is a Folder. However, when we click on this second-level folder the GetItem and GetItems methods are fired, but GetFolderContent is not, so nothing happens in the CME when we try to drill down.

What is the chain of method calls when we click on a nested folder, and which method is responsible for showing the list of items in a nested Folder?

1 Answer 1

9

For starters it is important that you implement all of these methods correctly, and that you have a clear definition of what is a EclItemTypes.File and what is a EclItemTypes.Folder.

Let me try to explain based on my Flickr ECL provider example, the IContentLibraryContext.FindItem(IEclUri) I chose to return null, which basically forces ECL to call IContentLibraryContext.GetItem(IEclUri) instead.

IContentLibraryContext.GetItem(IEclUri) makes sure the correct ItemType is being returned:

public IContentLibraryItem GetItem(IEclUri eclUri)
{
  if (eclUri.ItemType == EclItemTypes.File && eclUri.SubType == "img")
  {
    return new FlickrPhoto(...);
  }

  if (eclUri.ItemType == EclItemTypes.Folder && eclUri.SubType == "set")
  {
    return new FlickrPhotoSet(...);
  }

  throw new NotSupportedException();
}

This provider only has two item types (IContentLibrary.DisplayTypes), if it would support more, the above method would have more conditions (you might want to separate them out in a private method which you call from IContentLibraryContext.GetItem(IEclUri)).

IContentLibraryContext.GetItems(IList<IEclUri>) is there to filter out duplicates from BluePrinted Publications for instance.

public IList<IContentLibraryItem> GetItems(IList<IEclUri> eclUris)
{
  List<IContentLibraryItem> items = new List<IContentLibraryItem>();
  IEnumerable<string> uniquePhotoIds = (from uri in eclUris
                                        where uri.ItemType == EclItemTypes.File 
                                        && uri.SubType == "img"
                                        select uri.ItemId).Distinct();

  foreach (string id in uniquePhotoIds)
  {
    string itemId = id;
    var urisForPhoto = from uri in eclUris
                       where uri.ItemType == EclItemTypes.File 
                       && uri.SubType == "img" && uri.ItemId == itemId
                       select uri;

    foreach (IEclUri eclUri in urisForPhoto)
    {
      items.Add(GetItem(eclUri));
    }
  }
  return items;
}

Then last in IContentLibraryContext.GetFolderContent(IEclUri, int, EclItemTypes) you determine what to show, Folders and Files, or just Folders (when a Folder is opened in the tree view for example).

public IFolderContent GetFolderContent(IEclUri parentFolderUri, int pageIndex, EclItemTypes itemTypes)
{
  List<IContentLibraryListItem> items = new List<IContentLibraryListItem>();

  if (parentFolderUri.ItemType == EclItemTypes.MountPoint &&
      itemTypes.HasFlag(EclItemTypes.Folder))
  {
    // get photosets
    foreach (FlickrInfo info in Provider.Flickr.GetPhotoSets())
    {
      items.Add(new ListItem(parentFolderUri.PublicationId, info));
    }
  }
  // only return files if they are requested (itemTypes is EclItemTypes.File))
  else if (parentFolderUri.ItemType == EclItemTypes.Folder && 
           parentFolderUri.SubType == "set" && 
           itemTypes.HasFlag(EclItemTypes.File))
  {
    // get photos
    foreach (FlickrInfo info in Provider.Flickr.GetPhotosInSet(parentFolderUri.ItemId))
    {
      items.Add(new ListItem(parentFolderUri.PublicationId, info));
    }
  }

  return Provider.HostServices.CreateFolderContent(parentFolderUri, items, false, false);
}

As you can see, this method only deals items of type IContentLibraryListItem, these are so called unloaded items, just containing basic properties like title and modified date.

Now my IContentLibraryContext.GetFolderContent(IEclUri, int, EclItemTypes) example is rather limited, it expects only a basic structure and no folders below it. If you have a more complex structure you will probably want to use something like:

public IFolderContent GetFolderContent(IEclUri parentFolderUri, int pageIndex, EclItemTypes itemTypes)
{
  List<IContentLibraryListItem> items = new List<IContentLibraryListItem>();
  bool flag = itemTypes.HasFlag(EclItemTypes.File);
  string id = parentFolderUri.ItemId;
  int pub = parentFolderUri.PublicationId;

  if (parentFolderUri.ItemType == EclItemTypes.MountPoint)
  {
    // get base structure
    items.AddRange(GetMyItems(null, flag).Select(info => new ListItem(pub, info)));
  }
  else
  {
    // get items in folder
    items.AddRange(GetMyItems(id, flag).Select(info => new ListItem(pub, info)));
  }

  return Provider.HostServices.CreateFolderContent(parentFolderUri, items, false, true);
}

Where you handle getting the correct set of items (Folders only or Folders and Files) in a private method called GetMyItems (or whatever you want).

Also note I ignored pagination, else you will need to do something with pageIndex and use an overload of CreateFolderContent.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.