Search code examples
c#asp.net-coremodelasp.net-core-mvc

Nesting C# models for a recursive function


I am creating a file explorer with files and subfolders and more files and more subfolders. So my model is broken down into a file model and a folder model. The folder model can contain both list of files and a list of folders. I am looping through the folder structure recursively but I am struggling how I can get my object of this model to be filled throughout the model. My model will is as follows:

public class ExplorerFile
{
    public string BoxId { get; set; }
    public string ThumbnailBase64 { get; set; }
    public DateTimeOffset? ModifiedDate { get; set; }
    public string Name { get; set; }
    public string Link { get; set; }
    public long? Size { get; set; }
}

public class ExplorerFolder
{
    public string BoxId { get; set; }
    public DateTimeOffset? ModifiedDate { get; set; }
    public string Name { get; set; }
    public string Link { get; set; }
    public long? Size { get; set; }
    public List<ExplorerFile> Files { get; set; }
    public List<ExplorerFolder> Folders { get; set; }
}

The recursive function is as follows:

    public ExplorerFolder root_folder;

    [HttpPost]
    public async Task<ActionResult> BoxFolderExtract([FromForm] string BoxId)
    {

        // Get Root Folder info
        BoxFolder folder = await boxDrive.GetFolderInfoAsync(BoxId);

        // Define Root Folder Object
        this.root_folder = new ExplorerFolder()
        {
            Name = folder.Name,
            ModifiedDate = folder.ModifiedAt,
            BoxId = folder.Id,
            Size = folder.Size,
            Link = Path.Combine(BoxProductionDomain, folder.Id),
            Files = new List<ExplorerFile>(),
            Folders = new List<ExplorerFolder>(),
        };

        // Populate Root Folder recursively
        await PopulateFolderRecursively(folder, root_folder);

        return Ok(this.root_folder);
    }

    public async Task PopulateFolderRecursively(BoxFolder folderInfo, ExplorerFolder explorerFolder)
    {
        foreach (var entry in folderInfo.ItemCollection.Entries)
        {
            try
            {
                if (entry.Type == "file")
                {
                    Stream thumbnailContents = await boxDrive.GetFileThumbnailAsync(entry.Id);

                    var file = new ExplorerFile()
                    {
                        Name = entry.Name,
                        ModifiedDate = entry.ModifiedAt,
                        BoxId = entry.Id,
                        Size = entry.Size,
                        Link = Path.Combine(BoxProductionDomain, entry.Id),
                        ThumbnailBase64 = await ConvertStreamToBase64(thumbnailContents)
                    };

                    explorerFolder.Files.Add(file);
                }
                else if (entry.Type == "folder")
                {
                    BoxFolder folder = await boxDrive.GetFolderInfoAsync(entry.Id);

                    var subfolder = new ExplorerFolder()
                    {
                        Name = folder.Name,
                        ModifiedDate = folder.ModifiedAt,
                        BoxId = folder.Id,
                        Size = folder.Size,
                        Link = Path.Combine(BoxProductionDomain, folder.Id),
                        Files = new List<ExplorerFile>(),
                        Folders = new List<ExplorerFolder>(),
                    };

                    PopulateFolderRecursively(folder, subfolder);

                    explorerFolder.Folders.Add(subfolder);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"{ex}");
            }
        }
    }

The coding above reflects working model developed from the answer below but corrected for minor errors and for ASP.NET Core MVC.


Solution

  • You can do this, loop through each folder, and collect the files along the way.

    also create a root folder

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    public class HelloWorld
    {
        public static async Task Main(string[] args)
        {
            // Define Root Folder
            var root_folder = new ExplorerFolder();
            root_folder.Folders = new List<ExplorerFolder>();
            root_folder.Files = new List<ExplorerFile>();
    
            // Get Root Folder info
            BoxFolder folder = await boxDrive.GetFolderInfoAsync(BoxId);
    
            // Populate Root Folder recursively
            PopulateFolderRecursively(folder, root_folder);
    
            // Now the root_folder object should be populated with the entire structure
        }
    
        public static void PopulateFolderRecursively(BoxFolder folderInfo, ExplorerFolder explorerFolder)
        {
            explorerFolder.Name = folderInfo.Name;
            explorerFolder.ModifiedDate = folderInfo.ModifiedDate;
            // Initiate Linked Lists
            explorerFolder.Folders = new List<ExplorerFolder>();
            explorerFolder.Files = new List<ExplorerFile>();
    
            foreach (var entry in folderInfo.ItemCollection.Entries)
            {
                if (entry.IsFile())
                {
                    var file = new ExplorerFile
                    {
                        Name = entry.Name,
                        ModifiedDate = entry.ModifiedDate,
                        // Populate other file properties
                    };
                    explorerFolder.Files.Add(file);
                }
                else if (entry.IsFolder())
                {
                    var subfolder = new ExplorerFolder();
                    PopulateFolderRecursively(entry, subfolder);
                    explorerFolder.Folders.Add(subfolder);
                }
            }
        }
    }
    

    Note: code hasn't been tested