Johan Björnfot
Mar 24, 2011
visibility 5966
star star star star star
(1 votes)

Mirror other than content

By default mirroring handles content (and resources used by content such as linked files or PageObjects). I have heard some feedback that it would be nice if mirroring handled other things as well, in that specific case the question was regarding including page types. We might add page types and other things to mirroring “out of the box”, but for now it is possible to write a module that extends mirroring with that. In this post I will present a simple module that will include page types, dynamic property definitions, categories and tab definitions to the mirroring process.

NOTE: To be able to mirror page types you must uncheck “Enable validation” on the mirroring channel configuration. Otherwise the mirroring job will fail with a validation error if page types differ. The mirroring will handle creation of new page types and properties on page types but it will not handle deletion of page types or properties.

It is also possible to mirror other types of data. Data stored in DDS can be mirrored by simply adding the Identity of the objects to mirror to the EPiServer.Enterprise.DynamicDataTransferHandler. It is also possible to write an own import/export handler that gives you an exclusive stream to handle custom data. See my related post here regarding export of custom data and DDS data.

Access rights can be mirrored by combining this module with a prior module I wrote. There are however some settings/data that are not handled by this module (or the prior module), like Users, Groups, Enabled languages, workflow definitions etc. Some of them can probably be mirrored by writing a custom module but for example users is tricky since the passwords are hashed and thereby not readable.

One use case for mirroring is backup/failover. If you mirror your whole site then you will always have a running backup which also uses another database meaning that even if the “original” database for some reason goes down you could switch traffic to the mirrored site.

This code goes with standard “works on my machine” so any use of it is of own risk and unsupported. The module should be deployed to the bin folder of the Mirroring service on the source side.

 [InitializableModule()]
    public class MirrorAdditionalContentModule : IInitializableModule
    {
        //Mirroring service executes each job in own AppDomain so 
        //we dont have to worry about several jobs executing in parallell.
        private bool _exportedData = false;

        public void Initialize(InitializationEngine context)
        {
            MirroringEvents.SourceStartingJob +=
                delegate(object source, MirroringSourceInitializeEventArgs args)
                {
                     DataExporter.Exporting +=
                        new EventHandler(DataExporter_Exporting);
                };        
        }

        void DataExporter_Exporting(object sender, EventArgs e)
        {
            //There might be several packages in one job, 
            //send "extra" data only in first package
            DataExporter exporter = sender as DataExporter;
            if (!_exportedData && exporter.TransferType == 
                TypeOfTransfer.MirroringExporting)
            {
                _exportedData = true;
                
                //Unfortunately there is no easy way to keep track 
                //of changes on pagetypes, dynamic properties etc.
                //Therefore we always send all and let destination service merge.
                
                exporter.PageTypes.AddRange(PageType.List());
                exporter.DynamicPropertyDefinitions.AddRange(
                    PageDefinition.ListDynamic());
                exporter.TabDefinitions.AddRange(TabDefinition.List());
                foreach (int catId in CategoryList.LoadCategories())
                {
                    exporter.Categories.Add(Category.Find(catId));
                }
            }
        }

        public void Preload(string[] parameters) { }

        public void Uninitialize(InitializationEngine context)
        {
        }
       
    }
Mar 24, 2011

Comments

Apr 13, 2011 09:31 AM

Hi,

This is just what I am looking for, but I can't get it to build.
I can't find the correct includes for 'MirroringEvents', and 'MirroringSourceInitializeEventArgs'
Are you able to let me know what I need to get it building please? (I don't get the option to hover over the items to add the appropriate reference/include)

Thanks
Danny

seth@blendinteractive.com
seth@blendinteractive.com Jun 15, 2011 06:56 PM

Look in your webservice's bin folder. There are binaries for it there.

Joshua Folkerts
Joshua Folkerts Jun 15, 2011 06:57 PM

you can find them in
1. bin -> EPiServer.Enterprise
2. root->MirroringService->EPiServer.MirroringService

Mattias Lövström
Mattias Lövström Oct 27, 2011 02:42 PM

Regarding mirroring users, it is much easier to just use one database for users in a mirrored environment (supported with SQL membership), than mirror them.

error Please login to comment.
Latest blogs
Exploring Asset Lifecycle Management Approaches for Bynder and Optimizely SaaS CMS

Note: This is Part 3 of our Bynder integration series. For setup and filtering prerequisites, see Part 1  and  Part 2 . Introduction In my previous...

Vipin Banka | Jul 5, 2026

Unlock AI-Ready Experiences with Optimizely

Over the past few months, almost every customer conversation has shifted from SEO to AI readiness. The questions are no longer just: “How do we......

Madhu | Jul 5, 2026 |

Planning Your Bynder DAM and Optimizely SaaS CMS Integration the Right Way: Avoiding Asset Sprawl and Unnecessary Synchronization

Note: This is Part 2 of our Bynder integration series. If you missed the Part 1, check out " Implementing the Bynder DAM Connector with Optimizely...

Vipin Banka | Jul 4, 2026

Implementing the Bynder DAM Connector with Optimizely SaaS CMS: Lessons Learned

What I learned while integrating Bynder DAM with Optimizely SaaS CMS, exploring Optimizely Graph, and building a headless frontend experience....

Vipin Banka | Jul 3, 2026

Optimizely London developer meetup 2026: a round up

Well, what can I say? Last night we wrapped up! Yet another London Developer Meetup, hosted at the superb Lightwell venue And this is also a...

Scott Reed | Jul 3, 2026

AvantiBit Custom Settings for Optimizely CMS

AvantiBit Custom Settings is a free, Apache-2.0 Optimizely CMS add-on for typed, site- and language-aware configuration that stays out of content...

Enes Bajramovic | Jul 3, 2026 |