TL;DR: This is about how to organize a multisite Umbraco install.
This post may take a bit to explain things and I want to pre-qualify readers so that I don't waste their time. Therefore I will begin with a list of statements on who this blog post isn't for:
- If you're using Umbraco Cloud. This post gets very 'manual' mode pretty quickly and I'm not very confident Umbraco Cloud supports these sorts of things.
- If you build one site per Umbraco core and never plan to do a multisite install.
- If you build multisite solutions but don't care if you only divide clients by folders nor make any distinction between client site code and Umbraco code.
If you fall into one of the above categories, then perhaps a list of 100 Random Fun Facts is for you.
So who is this blog for?
If you write multisite installs and would like a clear separation between models, views, controllers and assets; this blog is for you.
If you have made it this far and no longer feel this post is for you, here is a link to a large list of cat images.
Ok then. If you are still reading this, we'll get on with the show.
It turns out that web dev\hosting has a few heuristics about it that create friction, such as the following:
- Cost - Dropping a single site into its own hosting plan can be wasteful on low-medium sites. A multisite solution can be appealing, but it is not without its drawbacks. Multisite hosting in one core also means mess up one site, you could take down the other sites.
- Upgrading - Upgrading the Umbraco core of one site is easy (insert comment here about breaking changes). Two is beginning to feel like work (especially when a new feature is released). Beyond that you just pray that a security alert isn't issued that affects all of your sites. A multisite install keeps that much more manageable.
- Portability - A low traffic marketing site does not require the horsepower of a full-on ticket purchasing site. However the moment the client has 'grand plans' or suddenly becomes an overnight sensation; a multisite install starts to feel like a lot of surgery to remove the conjoined websites. Or what if you want to fire the client (or they want to move on)? It'll be way easier to just give them their code if we can somehow isolate all of it.
- Customization - Ever met a client who says, "We just want a simple site except for these 2000 changes"? In a multisite solution, it's super critical to keep this client isolated; however traditionally that's been a tough riddle to solve.
So to summarize, the problem with multisite hosting is keeping all the clients nicely separated in code so that things stay tidy.
The solution (proposed)
Let's say you've made the leap of faith to do a multisite install like myself (I've hosted many). My current use-case is my local church. They were having provider issues and I finally stepped in to say that I would host it (at my own expense time + hosting). Naturally I didn't want to drop a bunch of money on a site that won't bring traffic like the next Red Bull event. The easy win for me is to co-locate my blog with the church site. Umbraco provides all of the means to keep the users from the church site out of my blog, so the focus of this blog isn't "how to setup a multisite" solution in Umbraco. That's easy, you can find resources to do so. The riddle I want to solve for you today is how to maintain each site in a multisite environment cleanly (or at least as clean as I can get it so far).
Let's work a bit backwards
So in order to show what I think is a clean solution, let's look at the solution; then talk about how I got there. The following image shows the final result. Each client gets their own project complete with their own models, views, controllers and frontend assets. No mixing of the two. Traditionally most multisite Umbraco installs have to co-locate views in a single folder. What's great about this solution is the Umbraco core is nearly pristine. The only thing that sullies it up a bit is the App Plugins folder and any other third-party package artifacts. For now that is not my battle. But perhaps one day that can be factored out as well.
The path to salvation
So next I want to share a brief list of obstacles I had to overcome. Splitting C# into separate projects is no secret, however splitting the assets and views away from the Umbraco project is a little tougher and there is a twist. Look at the image below:
Part one of this is as-follows:
- Use a post-build action to copy to the Umbraco project
- Make sure to not include these items in the Umbraco project (which is why they are greyed out)
- Set Git to ignore these files
This will make it all work as you would normally expect when you run Umbraco locally. I setup the 'client' projects as ASP.NET projects so include MVC ref's so that the razor views had proper intellisense.
The post-build commands are the same on all client projects (should you want to make a template):