Imagine a file system manager like Windows Explorer that shows files and folders from a computer in a treeview frontend.
This article is a partnership with Lucas Juliano, friend, workmate, and my blog’s editor.
There is no fun -- just writing methods and functions to interact with the system operational file system, so let’s use some Design Patterns to organize our C# code.
Before creating all frontend in VueJS, let’s create an API to access the file system and then use jQuery to show them.
At least, our File System Manager will earn a new clean frontend in VueJS, more friendly and, with more performance.
File System
API .NET Core C#
We are going to create a new .NET CORE API to interact and read all the files and folders from the file system.
Tag Helpers MVC .NET CORE
We are going to use the Tag Helper concept to create a file system manager component to use more than one time or more than one page.
jQuery frontend
Create a simple jQuery Frontend to interact with the DOM and consume the file system manager API.
VueJS frontend
Create a new frontend in VueJS, consuming the same API above. Lucas Juliano developed that frontend.
Design Patterns
For the API, we are going to use some Design Patterns like Repository, Dependency Injection, Strategy, and Factory.
I have written an eBook about Design Patterns, but I haven’t translated it into English yet.
jQuery and VueJS frontend preview
One of my students gave me a tip about showing in an article what to expect before showing any code.
His concern was the benefit of showing the final project before all explanations and coding to get there.
So Mario, for you, this is the final project.
jQuery frontend

VueJS frontend

The file system manager is not a big deal, so let’s check in more detail how we did it.
ASP.NET Core API Software Architecture
For understanding purposes, I had made a class diagram separating all responsibilities in the solution.

The FileSystemController knows about an IFileSystemService interface that contains all methods to return files and folders.
public interface IFileSystemService
{
IEnumerable<FileSystemObject> GetAllFileSystemObject(
string fullName);
object ToJson(
IEnumerable<FileSystemObject> objs,
IFileSystemFormatter fileSystemFormatter = null);
bool DirectoryExists(
string fullName);
}
The FileSystemService that implements IFileSystemService knows another interface called IFileSystemRepository to interact with files doesn’t matter if those files are in a database or in the file system itself.
public interface IFileSystemRepository :
ISelectRepository<Models.FileSystemObject>,
IDeleteRepository<Models.FileSystemObject>
{
bool Exists(
string fullName);
}
There is just one implementation of that repository interface that reads all stuff from the System.IO namespace.
In the future, if you want to create a logical file system using a database, you will only need to implement the IFileSystemRepository interface.
That is the Inversion of Control concept that we program using interfaces without knowing about their implementations.
The FileSystemService class is responsible for bringing all files and folders with a specific format. That is the goal of the IFileSystemFormatter interface.

We have two IFileSystemFormatter implementations, one for a Default format and others using the Humanizer library to format all dates and sizes with a more readable text.
public interface IFileSystemFormatter
{
object ToJson(
IEnumerable<FileSystemObject> fileSystemObjects);
}
That Formatter solution uses the Strategy Design Pattern.
One of my Blog’s contributors, Kleber Silva, had written an article about the Humanizer library.
ASP.NET CORE Configuration
The .NET CORE dependency injection settings code,
services.AddSingleton<IFileSystemRepository, FileSystemRepository>();
services.AddSingleton<IFileSystemService, DefaultFileSystemService>();
There are other settings in the Startup.cs file and, for performance, let’s remove NULL properties from JSON serialization.
.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddJsonOptions(opt =>
{
opt.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
opt.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
});
API .NET CORE Controller
The file system manager controller,
public sealed class FileSystemController :
Controller
{
private readonly IFileSystemService _fileSystemService;
public FileSystemController(
IFileSystemService fileSystemService)
{
_fileSystemService = fileSystemService;
}
public IActionResult Index(
string fullName = null,
string formatterName = null)
{
var data = _fileSystemService.GetAllFileSystemObject(
fullName);
var json = _fileSystemService.ToJson(
data,
FormatterFactory.CreateInstance(formatterName));
return Json(
json);
}
}
The Index action receives two parameters, a folder path and a type of format, default or humanizer format.
API .NET CORE Formatter classes, Services, and Repository
The DefaultFileSystemFormatter and HumanizerFileSystemFormatter,
public sealed class DefaultFileSystemFormatter :
IFileSystemFormatter
{
public object ToJson(
IEnumerable<FileSystemObject> objs)
{
var dateTimeFormat = "MM/dd/yyyy HH:mm";
return objs?.Select(obj => new
{
obj.Name,
Id = obj.Id.Replace(@"\", @"\\"),
obj.IsFile,
obj.HasChilds,
LastWriteTime = obj.LastWriteTime?.ToString(dateTimeFormat),
CreationTime = obj.CreationTime?.ToString(dateTimeFormat),
obj.Size,
obj.Extension
});
}
}



Sourav Kumar DasPosted Dec 26, 2019, 12:51 AM
Nice and useful article. Thanks for sharing.