For those of us building large applications with multiple teams it is nice to be able to separate a solution into multiple projects and modularize it. Asp.Net MVC3 does have a built in way to separate out sections of your project using a feature called "Areas."
To create an "Area" in the MVC3 app there is a template. You right click on the solution and choose Add -> Area. A dialog comes up to allow you to name the area. Once you are done the template will create the Area in an "Areas" folder in the MVC project. If you don't already have an Areas folder it will be added. If you already have other areas a new area will be added to the areas folder. Each area has its on Model, Views and Controllers folder. Each area can have its own layout, etc.
However, I wanted to separate out the areas into separate projects so we can have separate teams working on them and also only deploy the areas a users licenses for their system.
It turns out, after some trial and error that this is pretty easy to do.
Let's assume you have a single MVC application project and this will be your "shell" app. Now you want to create your first Area project. Here are the basic steps:
Right click on the shell project and "Add Area...". Type in the area name. This will create an Areas folder with your area in it. (This is not 100% needed but you do need the "Areas" folder and you can steal the XXXXAreaRegistration class for your application.)
Create a new MVC3 empty project in your solution to match your area. Move the XXXXAreaRegistration.cs file from the shell mvc project to the new project and adjust the namespace as applicable. (Or you can manually create an area registration class, it's a pretty simple class. Just use the Add area template generated one as an example.)
Edit the routes in the AreaRegistration folder as needed.
Delete the folder under the areas folder that the template wizard added.
Modify the web.config of the new project and take out the connection strings and the authentication, membership, profile, rolemanger sections. You will not need to deploy this web.config but the razor intellisense doesn't work without it during dev time.
Delete the global.asax file from the area's project or you will get extra default routes.
Create a virtual directory in the "Areas" folder of the shell project with the name of your area as the alias and point it to your "area" project. You will need to use IIS or IIS Express for this. I use IIS. For IIS Express you can use the appcmd.exe in the IIS Express folder or you can edit the applciationhost.config file.
That's about it. However, there is one other step... you need to get the dll and any projects that it references into the shell projects bin folder during build. There are two ways you can do this:
Reference the area project from the shell project. This is the simplest way to do it and it ensures the area projects as well as anything they reference are brought in automatically.
Modify the output folder on the area projects to build into the shell's bin folder. I would use this method if it weren't for what I consider a bug in Visual Studio 2010. For some reason it expects binaries for namespaces in the views/web.config file to be in the GAC or in a bin folder directly under the project folder. So, for third party extensions like DevExpress's or Teleriks you will get reference issues and intellisense won't work.
Create a post-build event on your "area" project to copy the build dll and references dlls to the "shell" projects bin folder. An example build event is: copy $(TargetDir)* $(SolutionDir)\ShellProjectName\bin . This turns out to be the best method and the one I am using due to the issues with method 1 and the bug in VS that method 2 exposes.
It turns out that is all you need to do. MVC3 uses the BuildManager class to find all references of the AreaRegistration class in all the assemblies in the bin folder. So, even though you never specify a reference in the shell project or its web confing MVC will still find your area registration classes and load the routes. You can verify it is working by using Phil Hacks routeDebugger which you can load usin NuGet.
Well, that's it... happy oranizing to you all. Let's hope my next blog entry doesn't take another year.