Architecting Multi-site Episerver Solutions
You may be aware that Episerver is a powerful platform that can be used for more than just a single website. You can utilize the underlying functionality of the platform to handle large-scale management of multiple websites in one single environment. Editors can share content throughout multiple sites, administrators can quickly launch new sites, and developers can work with one code base and database, making the sites easier to maintain.
Let's focus on the development of these multi-site Episerver solutions. How do you actually architect and develop these solutions? If you've ever tried to search for Episerver's best practices around this topic, you'll likely come up short. Sure, there's some documentation on Episerver World, but the documentation doesn't really provide any good guidelines or starting points. That's really because there's no correct way to do it. The Episerver platform doesn't force development teams to use any specific conventions when developing the multi-site solution.
So in this post, I want deep-dive into this topic to provide some considerations and approaches that you should think about before starting development on your next multi-site Episerver solution.
What is a Multi-Site Episerver Solution?
First, let's define what we are talking about when I say "multi-site". A multi-site setup is a solution where all sites share the same file structure (code base) on the web server and the same database for storage. So when you log into the Episerver website, no matter the domain name being used, you'll end up in the same editing and administration interfaces that the other websites utilize.
The websites in a multi-site setup can share content assets, such as pages, media, and blocks, and you can allow multiple editors to modify the content on multiple websites. Furthermore, administrators can create additional new sites that share the same root page, database, and code base. The additional sites are automatically mapped to the starting point for the hostname (typically called a "start page") and require no additional web server configuration.
Using a multi-site solution is great when you want to allow editors, marketers, merchandisers, or whoever else is managing the website to quickly spin up new websites, maybe for something like a marketing landing page, without the need for a development team to get involved in the process.
And let's not confuse this with the term "multi-tenant", which I'll define as a single web environment that hosts multiple IIS sites that could be using multiple Episerver code bases.
For this post, I'm going to start with a couple of baseline assumptions:
- I'll assume that you are primarily architecting a CMS solution. While the approaches can easily be extended or adapted for a Commerce solution, I'm not going to take that into consideration.
- I'll also assume that you are working within a single development team where the codebase could be connected to a single source control repository.
- I'll assume the Episerver solution is following a single server/environment path (for example, local to integration to pre-production to production, similar to how the environments are configured in DXC Service).
- Lastly, I'll assume you are using MVC. If you're still using WebForms, I'm sorry.
Let's get into it. Before you choose which approach to take, you should step away from Visual Studio and think about how the end solution will be used throughout all of the teams involved. Think about how the editors will edit, how the administrators will administrate, how the developers will develop... not only in the immediate term, but also down the road throughout the life of the websites.
Content and Template Re-Use
This will likely be the biggest consideration that will drive your architecture approach. If you know that each site will look completely different, and you won't share content between the sites, you may choose to architect the solution in a way so all of the code for each site is more compartmentalized.
Access Rights and Allowed Content Types
Consider access rights and allowed content types when creating new content. Will there be separate editors for each site? Will you lock down which pages can be created in each site (this goes back to content and template re-use)? Also think about the content areas. Do you want to prevent certain content types from being saved in a content area?
You may also want to think about the roles for the editors, content approval workflows, and what the editing interface would look like for a specific type of editor.
These considerations may drive how you set up your base classes for your content types. With a proper foundation and maybe some conventions, you could simplify the on-going development and maintenance of the code base.
Visitor and User Experience
Consider how the visitors will actually use the sites. Once again, this likely goes back to the content and template re-use considerations. Sure each site can have its own user experience, but you may want to think more specifically about search. Episerver Find allows you to use one index for multiple sites. Will the search experience allow you to search between all sites?
These considerations might also bring up how the other teams utilize and access the code base. Will there be specific development teams for each site in the solution? Do you have a separation between front-end developers and back-end developers? Will front-end developers be working directly in the code base?
On-going Maintenance, Development Phases, and Development Teams
Consider maintenance or development phases, and even future developers working on the code base. You'll want to make sure that the architecture is something you can maintain as the solution gets bigger and bigger. And again, going back to content and template re-use, if you need to develop a new site with a unique design and user interface, how easy will it be to create all of those new classes and views?
You'll want an architecture that new developers or development teams can quickly pick up and start working. It's not a bad idea to think about documenting your architecture, or at least documenting code that could be confusing to new developers.
These considerations should focus on making your life and other developer's lives easier. The last thing you want is a code base that everyone hates to work with.
Once you've thought about all of these considerations, and you know a general idea of what the usage of the sites and what the code base would look like, you can start thinking about the underlying architecture for the solution, and choose the approach that you want to build for the foundation of the site. While these approaches are not the end-all, be-all, nor are they one-approach-fits-all, they should give you a good idea about how to tackle the architecture of the solution. You might choose to do a combination of approaches depending on what considerations you came up with.
Use the standard MVC folder conventions
I think the baseline approach would be this one: just use the standard MVC folder conventions. You'll have a folder for your models, your controllers, and your views. This is a very common approach for single-site solutions, and it can be easily adapted for multi-site solutions.
This approach makes it easy for new developer and development teams to hop into the solution and quickly add value. You likely won't need to write a whole lot of documentation because it's a well-known MVC standard.
The drawback of this comes when you need to scale, or when there is limited content and template re-use between the sites. Those folders can get big quickly, and if each site has a unique landing page, you'll be creating models like look like "SiteOneLandingPage", "SiteTwoLandingPage", and so on. Maintenance may become a bear over time, but at least the architecture is understandable.
Use feature folders
Very similar to the previous approach, you could organize the content types by feature. This essentially means that the models, the view models, and the controllers for one portion of the site could live in one parent folder. Though, you'll still need to have the views live in the standard 'Views' folder (of course, unless you do some additional business logic with the ViewEngine).
This approach should make maintenance a little easier, but you'll still run into similar problems as before if there's not much content and template re-use throughout the sites. But still, new developers and development teams should be able to pick up on this architecture quickly.
Use MVC Areas
If you didn't know, Episerver does support MVC areas, though some configuration is needed in order to register the area with Episerver's routing system. If you search around, you'll find some developers in the Episerver community providing different solutions to utilize MVC areas. I recently used this approach in one of my Episerver solutions, and I'll provide some information on my architecture in a future post.
This approach is useful when there is very little content and template re-use. It allows you to separate the code for each site, and makes it easy for separate developers or development teams to jump into the code base and make updates.
If you use this approach, I highly recommend that you have a good set of base classes, and utilize the
AvailableContentTypes attribute on your content type models (more on that later). Doing this may require a bit more foundational code and documentation, but once it's in place, it'll make the editing experience a bit nicer since you won't see all of the other content types when creating pages and blocks.
Use a separate project or multiple projects in the solution
You may choose to break out some of the code, likely the content type models, into different projects within the same Visual Studio solution. This might be useful when the overall solution is complex, likely working with outside integrations or different data layers.
For example, if you are programmatically building pages within the CMS based on data synchronized an outside integration, you may need to move those content type models to a separate project that can be easily referenced.
I've personally used this approach a couple of times, mostly in Commerce solutions that involved integrations with outside ERP and PIM systems.
Use a NuGet package approach
Using a NuGet packages approach could be seen as the ultimate in code separation. And as you would expect, it is going to take a considerable amount of architectural and foundational code work. But the end result could be an approach that makes it easy for multiple development teams to contribute to the same Episerver solution.
Honestly, I've never actually seen a solution that uses this approach. I've only heard about it when talking to some other development teams.
Some Other Thoughts
Limiting available content types
I previously mentioned the use of
AvailableContentTypes in your content type models. The nice thing about this attribute is that this supports abstract classes. So you may choose to have a base abstract class for all of the content types for a particular site, then you can reference that abstract class in the attribute. Doing this will make the editor's lives so much easier, because it will dramatically clean up the available options in the "New Page" or "New Block" screen.
You might also want to start thinking about how you define the settings for each site. It's quite common that the site settings will somehow be attached to the start page for the site, whether directly through properties on the page type itself or through a settings block. Consider that you'll need to access these settings through code (for example, when developing a scheduled job), so you'll want to make sure you are getting the correct start page for the correct site.
If content and template re-use is a priority, or if there will be a need to quickly spin up and build out new sites, think about how the creating and editing experience will work. Some thoughts come to mind about how this can be streamlined:
- Create a site settings block type. When a new start page is built, you can just copy and paste another site's settings block to make the initial configuration quicker.
- Create a CSS theme system. Some type of mechanism that allows the editors to quickly choose how the overall site will look. You may also want to provide a way that editors can save additional CSS styles through the site settings page.
- Create a header and footer that can be easily modified. For example, consider turning the header navigation into a
ContentArea, and provide different types of navigation block types, so editors can quickly change how the navigation functions.
For multi-site solutions with different domains, you will need to use a 3rd party identity provider if you want to provide single sign-on between the sites, even if the sites are all hosted in the same environment. This authentication method can be a DIY identity solution such as IdentityServer4, or any of the many IDaaS providers available (Okta, Auth0, Azure ADB2C).
I hope this post provides a good starting point when developing a new multi-site Episerver solution. You can probably see that there's some things that you need to think about before you create your first class, and planning out the architecture before you get too deep into the project should positively affect the different types of people working within the solution.
What do you think? Have you every architected a multi-site Episerver solution? How did you approach it, and how has maintenance been? I've love to hear your feedback.
A special thanks to Episerver MVP Drew Null for providing his feedback on this topic.