ASP.NET MVC5 Feature Folders Structure
Structuring your files around business concerns is more natural way of handling projects than structuring them around technical concerns. The Separation of Concerns is applied in both approaches, but not both of them give the same desired clarity and ease for developers. This blogpost focuses on organizing MVC projects around feature folders, which represent the business concerns.
Most of the time developers make modifications related to a single feature (e.g. adding new fields, changing business rules, adding validation...). Structuring folders around interrelated files can make modification process simpler. The common MVC folder structure violates the rule of "Files that change together should be structured together". Structuring by business concerns embraces this very important rule.
Files that change together should be structured together.
Horizontal (Technical) vs. Vertical (Business) Folder Structure #
On the left side you can see the common MVC structure. On the right side you can see the feature folders structure of the very same project.
Styles
Shared.css
Login.css
Scripts
Login.js
Controllers
CoursesController.cs
DepartmentsController.cs
EnrollmentsController.cs
InstructorsController.cs
StudentsController.cs
UsersController.cs
Models
CourseEditModel.cs
CourseIndexModel.cs
DepartmentEditModel.cs
DepartmentIndexModel.cs
EnrollmentEditModel.cs
EnrollmentIndexModel.cs
InstructorEditModel.cs
InstructorIndexModel.cs
StudentEditModel.cs
StudentIndexModel.cs
UserLoginModel.cs
UserRegisterModel.cs
UserForgotPasswordModel.cs
Views
Courses
Edit.cshtml
Index.cshtml
Departments
Edit.cshtml
Index.cshtml
Enrollments
Edit.cshtml
Index.cshtml
Instructors
Edit.cshtml
Index.cshtml
Shared
_Layout.cshtml
Students
Edit.cshtml
Index.cshtml
Users
ForgotPassword.cshtml
Login.cshtml
Register.cshtml
_ViewStart.cshtml
Features
Courses
CoursesController.cs
Edit.cs
Edit.cshtml
Index.cs
Index.cshtml
Departments
DepartmentsController.cs
Edit.cs
Edit.cshtml
Index.cs
Index.cshtml
Enrollments
EnrollmentsController.cs
Edit.cs
Edit.cshtml
Index.cs
Index.cshtml
Instructors
InstructorsController.cs
Edit.cs
Edit.cshtml
Index.cs
Index.cshtml
Shared
_Layout.cshtml
Shared.css
Students
StudentsController.cs
Edit.cs
Edit.cshtml
Index.cs
Index.cshtml
Users
UsersController.cs
ForgotPassword.cs
ForgotPassword.cshtml
Login.cs
Login.cshtml
Login.css
Login.js
Register.cs
Register.cshtml
_ViewStart.cshtml
When you see this in your IDE (e.g. in Visual Studio), the distinction between the files is even greater, given that there is accompanied file type icon shown besides the filename.
Now, imagine you scale in amount of features, in addition to the standard N-Layer stuff like repositories, services, handlers, DTOs, etc... You will soon notice that things are starting to get messy in the technical folders organization. In the feature folders organization, each feature can scale on it's own, thus much easier to manage.
Food for thought:
- What if we put our CSS and JavaScript files also in these feature folders?
- What if one feature folder becomes so demanding on the UI that needs to be a full SPA view/module - can we structure it to use Angular?
- Can we develop one feature UI in Angular, another one in React, all other in classic server-side MVC, and stay sane with our overall project structure?
Example of single feature evolved as Angular application/module:
Features
...
ShoppingCart
Components
CartComponent.js
CartComponent.css
PaymentComponent.js
PaymentComponent.css
CartContainer.js
App.js
App.css
Index.cshtml
ShoppingCartController.cs
...
Benefits of using Feature Folders (over technical folder structure) #
Structuring your files by features (business concerns) makes things easier to find and manage.
- Time spent on navigation through Solution Explorer to locate interdependent files is drastically reduced since they are all in a single folder.
- You don't step over each other toes with your peers, thus, avoid spending time on fixing merge conflicts.
- You can scale and modify each feature on its own, independently from other features and even use different UI technology.
- You immediately understand what an application does and where to find necessary files for your given requirement.
- You can easily reuse similar features across projects by simply copying just a single folder.
- You can reason much easier about each feature just by looking in a single (feature) folder.
Implementing Feature Folders in ASP.NET MVC 5 #
To make this work in ASP.NET MVC 5, we should inherit the RazorViewEngine
and change the view location parts to ones that fit our new structure.
public class FeatureFoldersRazorViewEngine : RazorViewEngine
{
public FeatureFoldersRazorViewEngine()
{
var featureFolderViewLocationFormats = new[]
{
"~/Features/{1}/{0}.cshtml",
"~/Features/{1}/{0}.vbhtml",
"~/Features/Shared/{0}.cshtml",
"~/Features/Shared/{0}.vbhtml",
};
ViewLocationFormats = featureFolderViewLocationFormats;
MasterLocationFormats = featureFolderViewLocationFormats;
PartialViewLocationFormats = featureFolderViewLocationFormats;
}
}
Next, we have to add our newly created FeatureFoldersRazorViewEngine
in our application.
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
// ...
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new FeatureFoldersRazorViewEngine());
}
}
Summary #
Structuring our MVC projects following feature folders approach increases the productivity of our dev teams.
At our company, we have been using feature folders project structure on over dozens projects for over a year, and due to the high success and productivity boost, it became our default project structure on the presentation layer.