EPiServer - GetChildren from Nested File Structure by Name

Vote:
 

I am new to EPiServer so please let me know if there is a such library
dedicated for this specific use.

This is my problem:

Based on a given referencePath and Image name , I need to **getChildren()** of each given
folder so I can find the next folder by its name and GetChildren() and so an until I hit the last folder to get Image by its name to return its **contentLink**.

Referencepath : MomDirectory > Children1a > SubChildren > Images > Bad
Images > Img1.jpg

In EpiServer , I have contentFolderstructure like this

Family Directory

- MomDirectory 1

- Children 1a
- SubChildren
- img.jpg
- img1.jpg
- imgN.jpg
....
- Children 1b
- img.jpg
- img1.jpg
- imgN.jpg
....
- Children 1c
- SubChildren
- Images
- Bad Images
- img.jpg
- img1.jpg
- imgN.jpg
- Good Images
- img.jpg
- img1.jpg
- imgN.jpg
....
- - FatherDirectory 2
- Children 2a
- SubChildren
- img.jpg
- img1.jpg
- imgN.jpg
....
- Children 1b
- SubChildren
- img.jpg
- img1.jpg
- imgN.jpg
....
- Children 1c
- SubChildren
- img.jpg
- img1.jpg
- imgN.jpg
....


As I mentioned the very last folder contains the images where I get the final result I need which the contentReference of the image.
The below code is a manual way based on the sample referencePath. As you can see I get the first folder and gets its children to find the next folder and again get its children to find the next and so on.

// opening the family directory
var list = this._contentLoader.GetChildren<IContent>
(familyDirectory).ToList();
// finding the momDirectory by Name
var imageFolder = list.FirstOrDefault(x => x.Name.ToLower() ==
MomDirectoryName.ToLower());
// Get its Children
var list1 = this._contentLoader.GetChildren<IContent>
(imageFolder.ContentLink).ToList();
// find the Children Direcoctory by its Name from the MomChildren List
var imageFolder2 = list1.FirstOrDefault(x => x.Name.ToLower() ==
testName2.ToLower());
var list3 = this._contentLoader.GetChildren<IContent>
(imageFolder2.ContentLink).ToList();
var imageFolder3 = list3.FirstOrDefault(x => x.Name.ToLower() ==
"vintage collection");
var list4 = this._contentLoader.GetChildren<IContent>
(imageFolder3.ContentLink).ToList();
foreach (var l in list4)
{
if (l.Name.ToLower() == "subChildren")
{
var list5 = this._contentLoader.GetChildren<IContent>
(l.ContentLink).ToList();
var imageFolder5 = list5.FirstOrDefault(x =>
x.Name.ToLower() == "GoodImage");
var list6 = this._contentLoader.GetChildren<IContent>
(imageFolder5.ContentLink).ToList();
var imgk = list6.FirstOrDefault(x => x.Name.ToLower() == "img1.jpg");
contentReference = imgk.ContentLink;
}
}

This is my attempt to make it dynamic:

I tried to make a loop to go through each children but I hit a wall. How to create nested loop based on number of folders ?

private ContentReference GetImageReference(string imageTitle, string
referencePath)
{
ContentReference imageReference = new ContentReference();
var familyDirectory = ExternalImagesContentProvider.GetEntryPoint();
List<string> foldersList = referencePath.Split('>').ToList();
var parentLink =
var children = this._contentLoader.GetChildren<IContent>
(familyDirectory);

var lastItem = foldersList.Last().ToLower();
foreach (var folder in foldersList)
{
foreach (var child in children.Where(x => x.Name.ToLower()
== folder.ToLower()))
{
if (child.Name.ToLower() == lastItem)
{
child.ContentLink = imageReference;
}
}
}

return imageReference;
}

#199545
Nov 29, 2018 22:08
Vote:
 

Hi Gerle,

I think, if I understand your code right, you should update your method to something more like this:

/// <summary>
/// Gets the link for an image by recursing through the given folder structure.
/// </summary>
/// <param name="imageName">The image name.</param>
/// <param name="remainingPath">The remaining path.</param>
/// <param name="currentFolderLink">The current folder link.</param>
/// <returns>The content link to the image, or null if nothing matches.</returns>
private ContentReference GetImageReference(string imageName, IList<string> remainingPath, ContentReference currentFolderLink)
{
    if (string.IsNullOrEmpty(imageName) || remainingPath == null || ContentReference.IsNullOrEmpty(currentFolderLink))
    {
        return null;
    }

    var children = _contentLoader.GetChildren<IContent>(currentFolderLink);

    if (children == null)
    {
        return null;
    }

    var folderName = remainingPath.FirstOrDefault();

    // We have processed the entire path, now resolve the image link
    if (string.IsNullOrEmpty(folderName))
    {
        return children.FirstOrDefault(x => x.Name.Equals(imageName, StringComparison.OrdinalIgnoreCase))?.ContentLink;
    }

    // Remove the first item from the path list.
    remainingPath.RemoveAt(0);

    var folderLink = children.FirstOrDefault(x => x.Name.Equals(folderName, StringComparison.OrdinalIgnoreCase))?.ContentLink;

    if (ContentReference.IsNullOrEmpty(folderLink))
    {
        return null;
    }

    return GetImageReference(imageName, remainingPath, folderLink);
}

You can then use it as so:

IList<string> path = referencePath.Split('>').Select(x => x.Trim()).ToList();
var imageLink = GetImageReference(imageName, path, ExternalImagesContentProvider.GetEntryPoint());

However, if your image URL directly relates to your folder structure you should be able to do something much simpler, like:

var url = string.Join("/", referencePath.Split('>').Select(x => x.Trim()));
url = $"/{url}/{imageName}";

var imageLink = UrlResolver.Current.Route(new UrlBuilder(url));

/Jake

#199567
Edited, Nov 30, 2018 18:39
Vote:
 

One thing to keep in mind is that recursivley calling GetChildren can be very costly, especially if you have deeply nested content. If you are using something like Find or Vulcan for search, that may be a better route to take to get the content you are looking for.

#199584
Dec 02, 2018 18:48
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.