Designing Modularity on ASP.NET Core: Virtual File System

Image for post
Image for post

Introduction

Creating a modular application is hard. Building a modular User Interface is even harder. You need to separately develop module pages, components but make them integrated and working together as like a monolithic application UI.

Creating such a modular architecture requires to build a strong infrastructure. This is what we are trying to do with the open source ABP framework project.

In this article, I will focus on the Virtual File System, an important part of the modular infrastructure and will explain why we need it and how it can be developed on top of ASP.NET Core MVC.

Video presentation of this article.

User Interface Components

A typical ASP.NET Core MVC web application UI consists of static and dynamic resources.

Image for post
Image for post

Static resources include JavaScript, CSS, Image… files. These resources are requested by browser and responded by the Static Files middleware. They are generally located under wwwroot folder of the application.

Dynamic resources are Razor views, pages and components. They are handled, compiled and rendered by the Razor View Engine.

Both static and dynamic files are normally located in the physical file system (while the latest ASP.NET Core has a pre-compile option, the main point is same).

User Interface Components in a Modular Application

In a modular application, UI components are distributed into modules and generally embedded into module assemblies (DLL files).

Image for post
Image for post

The Static File Middleware and the Razor View Engine can not work with the resources distributed across module assemblies.

The Virtual File System

The Virtual File System is an adapter (wrapper) that makes ASP.NET Core work with the resources located other than the physical file system.

Image for post
Image for post

Our virtual file system implementation can work with three type of file locations:

  • Embedded Files: The files located in a DLL as embedded resource. These resources are registered to the Virtual File System on the application startup.

Dynamic files can override physical files and physical files can override embedded files (if located in the same path). In this way, your application can override UI components (like CSS files, JS files or views) of a module for customization purpose.

Virtual File Contribution

Modules should register/add their own embedded resources to the Virtual File System on the application startup. We have created VirtualFileSystemOptions for that purpose. Example usage:

context.Services.Configure<VirtualFileSystemOptions>(options =>
{
options
.FileSets
.AddEmbedded<MyModule>();
});

This code adds all embedded resources in the assembly of the MyModule class to the Virtual File System (VFS). Once all modules contributed to the VFS, we have a list of files and their paths (namespaces of an embedded is converted to a path) in an in-memory dictionary/collection.

IFileProvider Interface

ASP.NET Core uses IFileProvider interface to read files from the file system:

public interface IFileProvider
{
IFileInfo GetFileInfo(string subpath);
IDirectoryContents GetDirectoryContents(string subpath);
IChangeToken Watch(string filter);
}
  • GetFileInfo method is used to read a file info and content from a given path. It returns NotFoundFileInfo if given file does not exists.

We should implement this interface to return files from embedded/dynamic files. I will not share the implementation in this article, but you can guess it. If you want to know details, see our implementation and the documentation.

Configure Razor View Engine

Once we implement the Virtual File System, we can configure the RazorViewEngineOptions to add the new custom file provider:

context.Services.Configure<RazorViewEngineOptions>(options =>
{
options.FileProviders.Insert(0, new MyVirtualFileProvider());
});

Replace Static File Middleware

We normally use app.UseStaticFiles in order to serve physical files to browsers. We should also replace it by the Virtual File Provider. This part is also very easy. We can create such an extension method:

public static void UseVirtualFiles(this IApplicationBuilder app)
{
app.UseStaticFiles(
new StaticFileOptions
{
FileProvider = new MyVirtualFileProvider()
}
);
}

MyVirtualFileProvider is our example IFileProvider implementation. In your case, you can set FileProvider to any class that implements the IFileProvider interface as explained before.

Finally, we can use the UseVirtualFiles method instead of UseStaticFiles:

app.UseVirtualFiles();

Conclusion

I tried to briefly explain why we need to a Virtual File System to develop modular ASP.NET Core MVC applications and how to implement it.

I planned to write more articles on modular application development on ASP.NET Core based on my ABP framework development experiences.


This article was originally published on Volosoft Blog.

Volosoft

Volosoft

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store