Solution Layout for an MVC App

While it may seem easier to throw all code into one project, it is good practise to separate areas of code into different projects within a solution. This helps promote good design with principles like loose coupling and high cohesion. A solution layout I like is:

  • Domain – contains the domain layer and data interfaces (in their own sub folder) and, if necessary can reference the Infrastructure project.
    • DataInterfaces *
  • Infrastructure – contains plumbing code for functions such as logging and reporting, should not reference any other projects.
    • Logging
    • Reporting
  • Infrastructure.Data – contains data access code and references the Core and Infrastructure projects. Whilst some may put this in the infrastructure project, I prefer Domain to be able to reference Infrastructure which causes a circular reference if data access code is kept there.
  • Tests – self explanatory – references any projects that need tests. Each project has a subfolder to contain it’s tests
    • Core
    • Data
    • Web.Controllers
  • Web – contains the core of the MVC project including the views and Global.asax, some files and folders have been moved around and models and controllers have been moved into different projects. The web project references all other projects except Test.
    • Public
      • css
      • images
      • javascript
    • Views
  • Web.Controllers – contains the controllers and also the RouteRegistrar class. Splitting the controllers into their own project does cause some extra initial work but a good argument for doing this can be found here.

*Indented items represent folders and sub folders within the projects.

The Solution Explorer should look similar to this when done:

image

All projects are class libraries except for the Web project which is MVC2. Web Content folder has been renamed to public and sub folders added and script and css files moved into it. HomeController has been moved to the Controllers project and the Controllers and Models folders have been deleted.

To get this solution to run:

  1. Set Web as Start Up Project
  2. Add a reference to Web.Controllers from Web.
  3. Add a references to System.Web, System.Web.MVC (2.0.0.0) and System.Web.Routing from Web.Controllers.
  4. Add the RouteRegistrar class to Web.Controllers.
  5. Amend Global.asax.cs Application_Start to use RouteRegistrar.RegisterRoutes.
using System.Web.Mvc;
using System.Web.Routing;

namespace Furld.Web.Controllers {
    public class RouteRegistrar {
        #region Class Methods

        public static void RegisterRoutes(RouteCollection routes) {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new {controller = "Home", action = "Index", id = UrlParameter.Optional} // Parameter defaults
                );
        }

        #endregion
    }
}

I also have a preferred folder structure which looks like this:

  • Main project folder – this is what gets committed to source control
    • Docs
    • Lib – contains all libraries I reference (e.g. nunit.framework.dll, ninject.dll etc).
    • Src – contains the solution file and the projects, each in it’s subfolder (Core, Data …).
    • Tools – contains tools used in the project, both those that require installation and those where I am just using libraries (e.g. NUnit-2.5.4.10098.zip).

This layout has a few changes from my normal layout partly prompted by Rob Conery’s http://mvcstarter.codeplex.com/ and some investigation of http://www.sharparchitecture.net/.

Leave a Reply