World is now on Opti ID! Learn more

Johan Björnfot
Feb 12, 2010
  5355
(0 votes)

Mirroring – Modules and Custom code

In this post I will go into more detail about how the mirroring service works and how that affects modules and custom code.

As I mentioned in my previous post the mirroring job is executed in a separate application from the site. This has some implications when it comes to modules and external code. For example if you use custom properties on your site then the assembly containing the custom properties must be loadable from the mirroring service. So you have to deploy the assemblies to the bin folder for the mirroring service.

Event handlers

Another thing to be aware of is how to attach custom event handlers, e.g. to hookup to DataFactory events. Before I give any recommendations a short description of the internals of MirroringService is needed.

Each time the mirroring service starts a mirroring job (either acting as a source or as a target) it will create a new AppDomain and initialize a “CMS runtime” inside the new AppDomain. With “CMS runtime” I mean that functions such as DataFactory, DynamicDataStore, ObjectStore, VirtualPathProviders etc are initialized and functional. The initialization works in the way that the service reads the site configuration and initializes the functions according to the configuration. After the mirroring job is finished the AppDomain is unloaded.

One reason a new AppDomain is created for a mirroring job is that then one mirroring service can serve several sites and handle concurrent jobs. That means for example that when there are several sites in an enterprise scenario they can share the same mirroring service (they can though be configured to use separate mirroring services if that is preferred). Another reason is that we want the service to be “stateless”, that is it holds no internal state. It gets a job request and then initializes the runtime, executes the job and when the job is finished everything is cleared and no state is saved inside the service.

During the initialization of the new AppDomain the mirroring service will scan the bin folder for assemblies that want to be part of initialization. The scanning will be performed both for PlugInAttribute and for new MEF initialization as described in New initialization.

So what about hooking up event handlers? The way to go is to either use the new MEF initialization (recommended) or use the PlugInAttribute with a static Start method. Using HttpModule will however not work. The reason for that is because even though the Init method of your HttpModule will be called, that code will not execute in the correct AppDomain meaning there is no way to access e.g. the initialized DataFactory.

Web context

Another thing to be aware of is that the code executed as part of the mirroring job executes without web context. That means that event handlers and other code need to be implemented so they can execute without web context. There are helper classes like EPiServer.Web.VirtualPathUtilityEx (works like System.Web.VirtualPathUtility) and EPiServer.Web.Hosting.GenericHostingEnvironment (works like System.Web.Hosting.HostingEnvironment) that can be used instead of their counterparts in .NET framework. They are designed to work as the .NET classes but they also works without web context. For example:

  • System.Web.VirtualPathUtility.ToAbsolute(virtualPath) can be replaced with EPiServer.Web.VirtualPathUtilityEx.ToAbsolute(virtualPath)
  • System.Web.HostingEnvironment.VirtualPathProvider.GetFile(virtualPath) can be replaced with EPiServer.Web.GenericHostingEnvironment.VirtualPathProvider.GetFile(virtualPath)

Service location

The installer will install the mirroring service in a folder called MirroringService under the site root. It will be configured as a seperate site in IIS with a separate AppPool which means that it runs in its own process. It is possible to manually copy the MirroringService to another server and set up an IIS site there pointing to the service folder. One thing to remember if the mirroring service is relocated to another machine is that the VirtualPathProviders for the site must be configured so they can accessed from both site and service. This typically means that you would configure them to use a file share. Another thing that needs to be changed if the mirroring service is relocated to another machine is that the WCF endpoints and protocol used for communication between service and site (event replication and source service endpoint) has to be reconfigured to the new location and the binding has to be changed from from net.pipe to something (e.g. net.tcp) that works between machines.

Feb 12, 2010

Comments

Please login to comment.
Latest blogs
Make Global Assets Site- and Language-Aware at Indexing Time

I had a support case the other day with a question around search on global assets on a multisite. This is the result of that investigation. This co...

dada | Jun 26, 2025

The remote server returned an error: (400) Bad Request – when configuring Azure Storage for an older Optimizely CMS site

How to fix a strange issue that occurred when I moved editor-uploaded files for some old Optimizely CMS 11 solutions to Azure Storage.

Tomas Hensrud Gulla | Jun 26, 2025 |

Enable Opal AI for your Optimizely products

Learn how to enable Opal AI, and meet your infinite workforce.

Tomas Hensrud Gulla | Jun 25, 2025 |

Deploying to Optimizely Frontend Hosting: A Practical Guide

Optimizely Frontend Hosting is a cloud-based solution for deploying headless frontend applications - currently supporting only Next.js projects. It...

Szymon Uryga | Jun 25, 2025

World on Opti ID

We're excited to announce that world.optimizely.com is now integrated with Opti ID! What does this mean for you? New Users:  You can now log in wit...

Patrick Lam | Jun 22, 2025

Avoid Scandinavian Letters in File Names in Optimizely CMS

Discover how Scandinavian letters in file names can break media in Optimizely CMS—and learn a simple code fix to automatically sanitize uploads for...

Henning Sjørbotten | Jun 19, 2025 |