Organizing ASP.NET MVC solutions

Recently, a question came up on Twitter around your favorite project structure/solution organizing for ASP.NET MVC projects. I’ve toyed around with quite a few different strategies for structuring projects, and I’m currently settled around one that gives me the most flexibility. It’s extremely simple:

That’s it, two projects. So what goes in each project? Let’s first look at the UI project. The UI project contains only website content and contains no code. And I mean no code. This includes:

No controllers

No models

No Global.asax.cs

NO CODE AT ALL

Why no code? Because when the UI project contains only UI content and no code, my UI project now matches the deployment structure. It contains:

Views

CSS

Images

Global.asax

Web.config

Reference to the Core project

Since my UI project structure matches my deployment structure, it makes it a lot easier to figure out how the deployment should work. With controllers, models and so on in the mix, it becomes more difficult to see what gets included for deployment (the Content, Scripts and Views folder) versus what is left out. We can then organize two different concerns separately: our content and our code.

So where does code go? That’s the other project. I call it “Core”, but it can be anything. All code goes in one project, that includes our persistence model, view model, controllers, repositories, ORM mapping definitions, EVERYTHING.

Organizing the code

As far as organizing the code – I prefer keeping things simple. If I had my druthers, the UI project wouldn’t compile at all – it would just be a folder, holding content. Its “bin” folder would merely get populated by the output of the Core project.

Otherwise, I use folders to organize code. Projects are okay for organization, but they’re pretty rigid and tend to lock you in to layers and structure that are quite, quite difficult to change. I’ve already been burned a couple of times on large projects making a mistake in my project structure, and found that this approach tends not to scale. I’ve even run into teams with upwards of 100 projects, with only a half-dozen actual deploy targets! Remember, compile time is largely a function of the number of projects. 1000 files in a single project will compile much much faster than 100 files in 10 projects. At least an order of magnitude faster in cases I’ve seen.

Another issue I ran into was the difficulty in re-organizing code if you’re locked into a project structure. Besides just a sloooooooow Ctrl+F5 experience, it can be quite frustrating to realize you’re going to hose your entire source control log history because you want to move a file to a different project. In one recent hair-pulling re-organization experience, we basically lost our entire log history because we couldn’t do basic source control commands for a re-organization. This is exacerbated with source control systems like TFS which embed source control information in the actual project files. In our case, we had to delete all of our projects and re-create them by hand. Moving folders is waaaaaaay easier than dealing with projects and dependencies. You will want to re-organize your code, in a major, major way at some point.

If you’re having problems with layering your codebase – projects are a great way of dealing with this problem. It enforces dependencies quite nicely, basically forcing you to follow certain rules. However, once you get to the point where you’re starting to create a “Common” project, a “Configuration” project, a “Mappings” project and so on, consider rolling things back up into one project. Continuing down the project path will introduce friction in just basic everyday coding tasks, so at some point, it’s just not worth it.

So why not just do one UI project? Put all the code in there, and get the absolute fastest and the most flexible experience? Content structure is a completely different concern with completely different reasons for change than organizing code. However you decide to organize your code, keeping the code out of the UI project ensures that you don’t mix code and content organization.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.

I’m not structuring it this way (UI project) but I agree fully about preferring folders. That’s the same reason why tests shouldn’t ‘mirror’ project structure. Saw recently security assembly which had 2 tiny classes. I could live with managing dependencies but i can’t peacefully watch how build get’s damn slow with no good reason.

What are reasons you use internal development server instead of IIS?
I see IIS more ‘production environment’ like. And there is no need for waiting on firing up dev server.

Deciding on your project structure just so if you need to change it in the future you can get round TFS loosing the history seems a bit odd.

You can keep the history of files in TFS between projects you just have to exclude them from the project itself, move it in source control view and then include it in the new project (if I remember correctly).

Thanks for the article! I would appreciate a sample project as well, as I am a bit confused on how to return views from controllers which are in a different assembly. It seems like this would cause an unwanted dependency on UI from Core.

I’m using another name for code layer. There is “UI Process Components” for this in Microsoft’s Application Architecture Guide (http://www.codeplex.com/AppArchGuide). I think it’s for this purpose ha? If I’m wrong, please warn me. Anyway, my structure of asp.net mvc presentation layer is:

You never move files in Solution Explorer between projects. You move them in TFS Source Control Explorer, then re-add them back into the project using Solution Explorer. That way you keep your history.

nachid

What’s the secret to have global.asax and global.asax.cs in two differents projects.

I tried your solution putting them into two separate projects but my solution didn’t compile
I got this error
Could not load type ‘myProjectl.Web.Global’

Hi. Is there any way to get helper menus work ?
I mean Visual Stiodio contextual actions like Add View… when clicking on controller action header.Resharper does it, but views lands in Core project instead of UI.. Thanks in advance

I like this approach, however 2 details I was unable to resolve, my UI project files (.csproj, .csproj.user) and still in the UI directory – and don’t need to be deployed. I can live with that unless there is a way around it.

But the annoying thing is the UI project DLL’s are still created despite there being nothing to compile. I tried this with a bare bones web application containing nothing and it still created a 3KB DLL.

I am reorganizing my MVC app – new business requirements are causing it to grow beyond early expectations and was wondering what kind of “gotcha”s I need to avoid.

It looks like I just need to create a “Core” project and a “UI” project, copy all the files into their respective projects, delete the original files, and add a reference to the Core project in the UI project. Highlighted folders in the uploaded PNG would go in the UI project.
Is there anything I am missing?

Edit: oops, I think Scripts should go to UI too.

David Buckley

Just a pont what type of project is core and ui are they just another mvc 4 project type ?

jbogard

Sorry, this post is insanely old and out of date. Just do one project, don’t create two projects.

Ads

About Me

I'm the chief architect at Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.