Multisite feature in EPiServer 7.5
Even in previous version it was possible to have several EPiServer sites sharing the same database and configuration files (often referred as Enterprise setup). However there was a one to one relationship between IIS instance and EPiServer site meaning each EPiServer site needed to have an own IIS instance configured. So even when using same IIS application pool the sites run in different AppDomains.
One consequence of running in separate AppDomains is that static properties like PageReference.StartPage or Configuration.Settings.Instance will not be shared between sites and hence have different static values in each AppDomain. It also has the consequence that event replication was needed to be configured between the sites to get cache invalidation to work.
Multisite in 7.5
In EPiServer 7.5 multi-site handling has been changed so now a running EPiServer instance is multi-tenant meaning a single EPiServer application running in one AppDomain can contain several EPiServer sites.
The take advantage of this the DNS/IIS should be configured so the requests are routed to that IIS application. You can e.g. have a wildcard configuration so all request of *.mydomain.com is routed to the IIS application. Then it will be possible to dynamically create/delete new sites like newcampaign.mydomain.com without doing any IIS/DNS configuration at all.
It is of course still possible to configure to run sites that share database in separate IIS instances. For example it can be good to separate large sites to different machines (to avoid that they share the same resources like memory). When doing so you need to configure remote events though.
Configuration changes
Previously site settings (like e.g. SiteUrl, StartPage) where defined in the configuration files. That had the consequence that when a site was added/removed the configuration file had to be updated and hence the applications where restarted. We have removed away site settings (like SiteUrl, StartPage, host mappings etc.) from the configuration files and instead those values are stored in database. This make it possible to add/remove sites dynamically without having to update configuration files and hence application restarts can be avoided
This also simplifies deployment/development scenarios since the configuration files does not need to contain as much environment specific settings.
SiteDefinition
To be able to run several sites in the same domain static properties like ContentReference.StartPage and Settings.Instance.SiteUrl must return differently depending on context (in previous versions these properties where “truly” static throughout the application). We have achieved this by letting those properties delegate to SiteDefinition.Current (resides in namespace EPiServer.Web).
SiteDefinition.Current is resolved from the request, meaning a comparison will be done where the host from the request will be matched against all sites from SiteDefintionRepository. The site with a host matching the request will be returned. If no match is found or if the current thread is not executing on a web request the site registered with wildcard host '*' will be returned. If no wildcard site is defined a default SiteDefinition is returned where common settings like e.g. RootPage is set but StartPage will be ContentReference.EmptyReference and SiteUrl will be null.
That means that you can add host '*' to one site if you want that site to be returned from SiteDefintion.Current when there is no web request, this can be useful e.g. when running scheduled jobs. Another possibility for code that is not running on a web request (like scheduled jobs) is to assign SiteDefinition.Current then that assignment will be set for that context.
Also worth noticing is that there is one initialization for the application where all sites are initialized (unlike before where the initialization where for a specific site since each site run in a separate AppDomain). So if you have some custom initialization module that are site dependent you could use SiteDefinitionRepository.List() to get a list of all defined sites.
Site Management
Sites are managed in admin mode under “Manage Websites” in admin mode. Here you can create new sites, delete unused sites and configure sites (for example specify language-host mappings). So by default is site handling a task for administrators.
However it is possible to let site creation be done by editors. One way to achieve this is to set up an event handler for IContentEvents.PublishedContent and in the event handler check if the content is of your StartPage type and if so creating a new site by storing a new instance towards SiteDefinitionRepository.
I'm a little bit curious about what you write about development/deployment scenarios.
Often the staging and test and dev environments have different configuration values and the configuration files are updated during an automated deployment. Now with 7.5 when configuration values are in the database how does that simplify deployments?
Instead of config transforms the databases have to be updated either using some SQL Script or using (if possible) the configuration API through an initialization module - which would read the enviroment specific values from somewhere and updated the configuration settings in the database.
Thanks Johan, a great article! I especially like the part where editors can be enabled to create their own sites, such as campaign sites for example which really speaks for agility.
The values that are stored in db are e.g. SiteUrl and StartPage, those values are different in the different environments (like, test, dev, production) so normally you should not want that to be part of your deployment.
Or did I misunderstand something? what values where you refering to when saying it needs to be handled through sql script or InitializationModule?
Johan, I was thinking about the SiteURL, a common use case might be the staging env. which might have a database which is overwritten frequently by production database to keep things in sync, but then the sitesettings have to be fixed as well.
Or when there might be a need to set up a new dev. env using production data and then the configuration would be need to be updated again.
Setting up a dev environment could be solved by setting up a empty database and then import content into the site (that is have the production data available in an .episerverdata package). This is how we do it in our developement.
You could use Export/Import as well to transfer data from production to staging (or mirroring if you want to run it automatically).
However there are also powershell cmdlets Set-EPiSiteDefinition and Add.EPiSiteDefinition in EPiServerInstall.CMS that you can use to either create a new site or update an existing site (e.g. SiteUrl)
This is one of the coolest features of 7.5 by far, and will really help with Enterprise scenarios. Fiddling with IIS and deployment just for a campaign site was never much fun!
If I have a muilti-site with multiple startpages for different countries each having their own language as default, how do I do this? I have created the sites and they are all default to EN. Do I just create the startpage in the local language and the remaining pages will be default in that language?
I have a single site and I get that ContentReference.StartPage is empty when I run a scheduled job. SiteDefinitionRepository contains just one SiteDefinition, so why does it fall back to empty? And where do I set up a wildcard site, which I shouldn't have to when I only have one site?
I agree with you there @Mathias Frodin, if there's only one site definition it should return that instead of empty but maybe there's a good reason for it.
You can add a wildcard for a site in admin mode under System Configuraton -> Manage Websites -> Edit Website by adding * for host name.