Simplifying Projects with a Folder-by-Feature Structure

Ryan Duffing
C2 Team Member Alumni

Working in the Episerver ecosystem is one of the lowest barriers to entry for development in a CMS platform I have encountered. If you’re familiar with ASP.NET MVC, you can get started developing with Episerver within a few hours. Of course, there is lots to learn around Episerver than simply building a few pages and blocks, but generally a developer can hit the ground running and spin up a site quickly with ease.

As I’ve worked more with Episerver, one of the few things with room for improvement is with the structure of a project. Episerver follows traditional ASP.NET MVC structure, meaning that there is an individual folder for Views, Controllers, and Models. The traditional structure works great for smaller projects because it offers clean organization, and most developers that have worked with ASP.NET MVC will know where to find code they are looking for.

Below is a sample of what a traditional structure for ASP.NET MVC looks like:

Unfortunately, as your project grows the traditional structure falls apart. Over time code becomes harder to find, the project is harder to maintain, and there is a lot of scrolling around the project to change code for a single feature. This is where the concept of feature folders come in handy.

Before I dive into the details of how Episerver implements feature folders, I’d like to introduce an approach I discovered years ago when I was working primarily with AngularJS development. Coined the “folder-by-feature” structure by John Papa, this structure gives stronger guidelines to organizing projects into several folders with each folder representing a single feature. Each folder includes any JavaScript, CSS, HTML, and other code required to create and maintain that single feature.

John Papa argued that this style of folder structuring would help the application from becoming cluttered, make it easier to find code, while keeping projects in alignment with LIFT guidelines. LIFT consists of the following: (L)ocate code easily, (I)dentify code at a glance, (F)lat folder structure as closely as possible, (T)ry to not have duplicate code. If you’re interested in other recommendations John Papa makes for an AngularJS project, you can find them all here.

Using the “folder-by-feature” structure in accordance with LIFT has become my go-to for all development projects I have had the pleasure of architecting. Taking this architecture beyond AngularJS projects, I’ve used this structure to direct my ASP.NET MVC projects, my WordPress projects, my Laravel projects, and now my Episerver projects.

Setting this structure up in an Episerver project is extremely simple. All that is required is creating a new RazorViewEngine and adding it to the collection of ViewEngines available to the Episerver application you are working on. A RazorViewEngine is a view engine that is utilized by the Episerver application to render web pages that use the ASP.NET Razor syntax.

Here is an example of what your RazorViewEngine may look like:

<p> CODE: https://gist.github.com/thec2group-blog/1faba08352c96189d0d41183a45b11f9.js</p>

At a very high level – the master location, partial-view location, and view location formats are saved to lists, each has a group of new locations added onto their lists, and then these lists replace their original default assignments.

There are three new locations I tend to use with Episerver to inform the application of where to look for my Razor views:

  1. Under a Views folder nested directly under the feature folder it represents. This is useful when a feature consists of one block or page, and does not have a lot of files underneath the feature folder.
  2. Under a Views folder within a Blocks folder that is nested under the feature folder. If you have a feature with multiple pages or blocks it helps to have the views for the blocks right next to your block controllers.
  3. Under a Views folder within a Pages folder nested under the feature folder. This is the same concept as when a Views folder exists within a Blocks folder. If you have multiple pages for a feature it helps the application be more organized to have the views for the pages right next to their respective controllers.

I generally have only had a use for the first option, but I add the other two options to plan ahead for more complicated features and to allow other developers to have more flexibility within the project. There are of course many more locations you can add, but these are the three that have been the most useful in the Episerver projects I’ve worked on.

After you have created your new RazorViewEngine, add it to the collection of ViewEngines that Episerver will use when rendering your Razor views. This needs to happen in the application’s Global.asax file under the Application_Start() method.

An example of what that may look like:

<p> CODE: https://gist.github.com/thec2group-blog/e4722f5e22d28b4ab2888c154ae12592.js</p>

This is the magic required to add your additional locations from your new RazorViewEngine into the ViewEngines that Episerver will use. By inserting your locations at position 0, it gives them the highest priority and that is where Episerver will look first when attempting to render your Razor views into web pages.

With these simple changes you can start developing an Episerver application using the feature folder concept, and have an application layout such as the one below:

Insights, Right to Your Inbox.