Try our conversational search powered by Generative AI!

Anders Hattestad
Sep 29, 2010
(1 votes)

Shame on you Mr EPiServer

Have started to investigate some mirroring issues @GarethKelly have reported regarding Itera.MultiProperty. But pretty soon (after I got the damn mirroring stuff to work :) )  I discovered that the mirroring service don’t just look at the IReferenceMap but also on the type of the property.

To get mirroring to work you need to (as muhammad kashif pointed out) copy your dll’s to the subfolder MirroringService\bin

I thought that if I made a reflector copy of PropertyUrl that copy should behave exactly the same as PropertyUrl. That is not the case regarding mirroring.

I tested this with creating a page with the 2 properties, and got these results.




Mirrored page


Reflector copy of PropertyUrl



Mirrored page


Strangly is that if I fill out the same values on the source page, the mirrored pages properties points to the same document (the correct)


Why is it like this?

If we do some reflectoring, we can se that there are special handlers for different kind of properties


So I though, great, I can make my own, but as far as I can see this stuff is registered inside DataExporter


This is extremely bad news for every developer of EPiServer that want to create custom properties. This makes mirroring a bit hassle.

One solution the overcome this shortcoming of mirroring 2.0 we could create a PropertyXhtmlString property on each page where we automatically add a href to each element from the IReferenceMap. But that would be counter productive.

There shouldn’t be any difference between a Reflector copy of PropertyUrl and PropertyUrl!

Is there anything I have overlooked Mr EPiServer :) ?

Added some thoughts 30. sept

After a god night sleep, I have thought some more about this mirroring issue,

In my opinion the first problem is that the mirroring service need to know the properties (have a copy of the dll’s) This approach have already given me problems with auto attaching virtual maps and other stuff. Its like that a telecom operator need to know what kind of person you are to be able to transmit your voice.. Its shouldn’t be like this at all.

Common, you have added a change log construction. That construct could have taken care of your extra needs. There is also already in place a SoftLinks construction (that could need some love) that could have provided you with what resources a page reference to.

The other problem is that before all properties had 2 sides. One data container side, and one display/edit side. With the stuff in the DataExporter you have introduced a 3. side. And left us developers with (as I can see) any methods to add code to this side. In the past you (Mr EpiServer)  have been reluctant to change code since it will break existing project. This new code breaks that rule big time.


Sep 29, 2010


Anders Hattestad
Anders Hattestad Sep 30, 2010 09:01 AM

Added some more thoughts

Sep 30, 2010 12:08 PM

We actually considered doing mirroring independent of custom modules. There are some nice benefits with that, one that deployment of custom modules would not be needed and another thing is that it would probably be a lot faster since you can then work with the “raw” data format.
The decision after some thinking was however not to implement it that way. The main reason was that several scenarios require that we need to be able to create PageData (which contains the custom properties) instances. Below are some reasons:

• There are a lot of modules out there that relies on DataFactory events such as CreatedPage, SavedPage, DeletedPage etc. So to get these events fired when doing mirroring as well then we need to create up PageData instances and save those through the ordinary DataFactory API.

• To be able to handle properties that implements IReferenceMap it is required that the property is instantiated (see below on more information about IReferenceMap).

• Using DataFactory API is also required to be able to support mirroring to custom PageProviders.

• For maintainability reasons we did want mirroring to use the same API as import/export (which works with PageData instances).

Regarding the event handlers in DataExporter and DataImporter they are not new in CMS6 but has existed in CMS5 as well so in that matter nothing new is introduced with Mirroring2.0 regarding that.

The idea with the event handlers is to expose an opportunity to handle extra logic for a property when it is imported or exported. A typical use case is when the property has some dependent external resource (like a PropertyUrl referencing a file or a PropertyXForm referencing an XForm) then the event handler is responsible for adding the actual resource (for example a file or an XForm) to the export package.

The events are publically static declared so you can register your own handlers for your custom properties.

The identity of a resource (for example a file or a page) might change during import (otherwise you would not be able to import the same package several times). To handle this scenario a property can implement IReferenceMap. The purpose of IReferenceMap is that a property that implements this interface will at import (before the property is saved) be called with a Guid map as parameter so the property can change its reference to the new identity.

Hopefully you now have some more knowledge regarding why it is implemented as it is. But of course there are always things we can do better. For example your idea of that resources automatically could be found and included in package is interesting and something I hope we can do more around. We are thankful for your feedback and will take that in consideration for upcoming versions.

Anders Hattestad
Anders Hattestad Sep 30, 2010 01:48 PM

Hi Johan
I can understand that you have made a choice and then sticking to that.

But after I read what you have said here, I’m wondering if the mirroring stuff is like a new episerver instance? Do it insert directly into the database. I guess so since if you had used the API that would have taken care of the page events.

That takes me to my current problem. How to attach myself to the DataExporter. I need to attach myself to the DataExorter instance that is running in the mirroring pool.

I have tried

[Serializable, PageDefinitionTypePlugIn]
public class PropertyTestPropertyUrl2 : PropertyString, IReferenceMap, IInitializableModule
#region IInitializableModule Members
public void Initialize(InitializationEngine context)
DataExporter.ExportPropertyEvent += new EventHandler((PropertyUrlTransform.ExportEventHandler));

public void Preload(string[] parameters)

public void Uninitialize(InitializationEngine context)
DataExporter.ExportPropertyEvent -= new EventHandler((PropertyUrlTransform.ExportEventHandler));

But this doesn’t work. Can you provide an example how we can make our own PropertyUrl property that actually work?

Sep 30, 2010 02:18 PM

When a mirroring job executes it actually creates an EPiServer.Enterprise.Mirroring,MirroringDataExporter (which inherits DataExporter). Since the event is declared as static it will not be inherited so instead MirroringDataExporter exposes it's own ExportPropertyEvent.

This construction is really not something we are proud of but since the event was declared static and we could not break backward compatibility this was how it was done.

So your code should run just fine if you instead hookup to MirroringDataExporter.ExportPropertyEvent (if you want your code to execute both for mirroring and ordinary export you typically hookup to both events).

Anders Hattestad
Anders Hattestad Oct 4, 2010 09:35 AM

It works by hooking up with MirroringDataExporter, but I see that the property is a RawPropertyData, so I have to parse they text instead of useing methods on my property. It's also a hassel since It's difficult to check what kind of type the different properties are.

And the strange part, is that I dont see any difference between this method and RemapPermanentLinkReferences(IDictionary idMap) from the IReferenceMap. But that is maybe only me. Guess the "correct" way of solving own properties is to save the value as html/xhtml and let the the parser handle the remapping of the urls.

Please login to comment.
Latest blogs
Introducing Image Transformer - AI Assistant for Optimizely

We've got something super cool to share with you, and it's all about giving your images a fresh spin. Image Transformer, the latest feature from ou...

Luc Gosso (MVP) | Feb 26, 2024 | Syndicated blog

Welcome 2024 Winter OMVPs

Hello, Optimizely community! We are thrilled to announce and welcome the newest members to the Optimizely Most Valuable Professionals (OMVP) progra...

Patrick Lam | Feb 26, 2024

Optimizely Opal... what it does actually do?

At Opticon 2023, Optimizely announced its first AI product Opal. AI is definitely the new tech buzzword in 2024 and with promises that AI will be...

Jon Jones | Feb 25, 2024 | Syndicated blog

How to add more Content Area Context Menu Item in Optimizely CMS 12

Hey folks, today I will share something related to Context Menu customization in the Content Area of Optimizely CMS. As you know, the content area ...

Binh Nguyen | Feb 25, 2024

Developer meetups in Stockholm & Helsinki

It's time for developer meetups! Next month we will be in Stockholm and Helsinki. Join us for getting the latest updates from Optimizely, be inspir...

Magnus Kjellander | Feb 23, 2024

Roll Your Own Security Headers

Proper security headers are a must for your Optimizely driven website. There are a variety of tools out there that will help with this, but when...

Ethan Schofer | Feb 21, 2024