0

I am working on a web application for managing files and folders. I am keeping files and folders in separate database tables, but when I retrieve a folder from the backend, it can have child items which can be either folders or files. So rather than deal with separate lists of files and folders in the frontend, I would like to combine them into a single Children property using a DTO class which has properties common to both files and folders. Then I can just display that single list.

Here's an example of how I'm mapping the items to that property:

  CreateMap<Folder, FolderDetail>()
                .ForMember(dst => dst.Children, opt => opt.MapFrom(src => src.SubFolders.Select(folder => new FolderChildItem()
                {
                     Id = folder.Id,
                      ModifiedDate = folder.ModifiedDate,
                       Name = folder.Name,
                       Type = "Folder"

                }).Concat(src.Files.Select(file => new FolderChildItem()
                {
                    Id = file.Id,
                    ModifiedDate = file.ModifiedDate,
                    Name = file.Name,
                    Type = file.Type

                }))));

This actually works fine, but the problem is I'd like to recursively map each subfolder's children, on down the tree until no more subfolders are found. Then I can have information contained about the entire tree underneath the main folder being returned by the backend and can display information about all files and folders contained underneath the main folder.

That necessitates adding a Children item to the FolderChildItem DTO. The Children item in the example is on the FolderDetail DTO which is returned at the top-level, the Children item itself being a collection of FolderChildItem's, which can have their own children. I've added a Children property to the FolderChildItem class, but I don't know how to get that mapping to go through recursively for all subsequent children.

  • 1
    Could you create a mapping from `SubFolders` and `Files` to `FolderChildItem` instead of manually mapping them using the constructors? Then AutoMapper should cascade down your objects (as long as you don't use `MaxDepth(int)`) – MichaelM Sep 17 '19 at 19:52
  • I could do that, but how do they get combined into the Children list? – AlexeiKaramazov Sep 17 '19 at 20:27
  • I found [this StackOverflow question](https://stackoverflow.com/questions/31220501/automapper-mapping-single-destination-property-as-a-concatenation-of-multiple-s) and created this [dotnetfiddle](https://dotnetfiddle.net/7XZUUh) from it. I'm not in love with the implementation but it may be what you need. There is also another answer on the above question that you could consider instead – MichaelM Sep 18 '19 at 13:53

1 Answers1

0

I took another run at it and came up with this:

  CreateMap<Folder, FolderDetail>()
                .ForMember(dst => dst.Children, opt => opt.MapFrom(src => GetFolderChildItems(src)));

 private IEnumerable<FolderChildItem> GetFolderChildItems(Folder src)
        {
            var folderChildren = src.SubFolders.Select(folder => new FolderChildItem()
            {
                Id = folder.Id,
                ModifiedDate = folder.ModifiedDate,
                Name = folder.Name,
                Type = "Folder",
                Children = GetFolderChildItems(folder)

            }).ToList();

            var fileChildren = src.Files.Select(file => new FolderChildItem()
            {
                Id = file.Id,
                ModifiedDate = file.ModifiedDate,
                Name = file.Name,
                Type = file.Type

            }).ToList();


            var childItems = folderChildren.Concat(fileChildren);

            return childItems;
        }

The GetFolderChildItems function will recursively concatenate all child items.