Legacy Event Adapter

Why do you want to use this extension:

With the release of SDL Tridion 2011 a fully functional TOM.NET API is available.

A lot of VB code was also migrated to the new .NET code base. This has allowed the API to be faster and more robust. During the migration it was very closely monitored that existing functionality and/or behavior remains unchanged when using the old legacy API and/or the GUI (Content Manager Explorer). However new features in publishing forced the new Content Management Explorer for SDL Tridion 2011 to use the Core Service for Publishing and Resolving. Also Audience Manager 2011 uses Core Service for contact import (which may create Keywords). After upgrade to 2011, TOM event handlers will no longer be triggered for publishing, resolving and (for Audience Manager contacts import) Keyword save.

This extension can be used to emulate those legacy events in the kernel in order to get back to a fully functional legacy event system.

Note 1:

When using the TOM API, TOM events as well as TOM.NET events will be triggered.
When using the CoreService or TOM.NET API, only TOM.NET events will be triggered.

Note 2:

Be careful not to let events trigger multiple times. So you should disable the MMC snap-in event configuration for the respective events.
For example when a KeywordSavePre event is enabled for TOM in MMC snap-in, and the LegacyEventAdapter is configured as legacyKeywordSaveEventsEnabled="true". Then a TOM API Keyword Save call will trigger the following events:

  • KeywordSavePre  -  because it is called through TOM

  • Keyword, SaveEventArgs, EventDeliveryPhase.Initiated  -  because also TOM.NET event will be triggered when TOM API is used

  • KeywordSavePre  -  because LegacyEventAdapter is configured to trigger legacy KeywordSave events from TOM.NET (and is subscribed to Keyword, SaveEventArgs, EventDeliveryPhase.Initiated)

  • Keyword. SaveEventArgs, EventDeliveryPhase.Processed  -  because also TOM.NET event will be triggered when TOM API is used

  • KeywordSavePost  -  because LegacyEventAdapter is configured to trigger legacy KeywordSave events from TOM.NET (and is subscribed to Keyword, SaveEventArgs, EventDeliveryPhase.Processed)

  • KeywordSavePost  -  because it is called through TOM

What it does:

The LegacyEventAdapter provides a way to trigger TOM events for those API calls where TOM API was not used. It is configurable in Tridion.ContentManager.config so TOM event types can be enabled or disabled, regardless whether it was enabled or disabled through SDL Tridion MMC snap-in.

The following legacy events can be triggered by the LegacyEventAdapter:

1.  OnCategoryPublishPre
2.  OnComponentPublishPre
3.  OnComponentTemplatePublishPre
4.  OnPagePublishPre
5.  OnPageTemplatePublishPre
6.  OnPublicationPublishPre
7.  OnStructureGroupPublishPre
8.  OnCategoryPublishPost
9.  OnComponentPublishPost
10. OnComponentTemplatePublishPost
11. OnPagePublishPost
12. OnPageTemplatePublishPost
13. OnPublicationPublishPost
14. OnStructureGroupPublishPost

1.  OnComponentResolvePre
2.  OnComponentTemplateResolvePre
3.  OnPageResolvePre
4.  OnPageTemplateResolvePre
5.  OnPublicationResolvePre
6.  OnStructureGroupResolvePre
7.  OnComponentResolvePost
8.  OnComponentTemplateResolvePost
9.  OnPageResolvePost
10. OnPageTemplateResolvePost
11. OnPublicationResolvePost
12. OnStructureGroupResolvePost

1.  OnKeywordSavePre
2.  OnKeywordSavePost

How to build:

There are two different projects: LegacyEventAdapter (Visual Studio 2010) and LegacyEventsFacade (VB6).

First open the LegacyEventsFacade project and build it by using the menu option File --> Make LegacyEventsFacade.dll.

Next open the LegacyEventAdapter project and make sure that all referenced assemblies can be found excluding the "Tridion.ContentManager.Interop.LegacyEventsFacade" as this will be built as a Pre Build event of this project. If they cannot be found, delete the reference and add the referenced assembly from your custom location.

Then open the properties of the project to make sure the paths in the pre-build and post-build events are correct. The pre-build event will make an interop assembly out of the LegacyEventsFacade, and the paths referenced probably need to be updated to the following to be able to build correctly: 

"$(FrameworkSDKDir)bin\tlbimp" "$(ProjectDir)LegacyEventsFacade\LegacyEventsFacade.dll" /out:"$(ProjectDir)LegacyEventsFacade\Tridion.ContentManager.Interop.LegacyEventsFacade.dll" /reference:"$(TRIDION_CM_HOME)\bin\client\PIA\Tridion.ContentManager.Interop.cm_defines.dll" /reference:"$(TRIDION_CM_HOME)\bin\client\PIA\Tridion.ContentManager.Interop.cm_tom.dll" /keyfile:"$(ProjectDir)LegacyEventAdapter.snk"

The post-build event will install the LegacyEventsFacade interop assembly and the LegacyEventAdapter assembly in the GAC. This probably does not need any change.

Build the LegacyEventAdapter project by using the menu option Build --> Build Solution.

Before configuring the LegacyEventAdapter make sure the Tridion.ContentManager.Extensibility.Events.LegacyEventAdapter.dll and Tridion.ContentManager.Interop.LegacyEventsFacade.dll are available in the GAC.

The component LegacyEventsFacade.EventFacade (LegacyEventsFacade.dll) should be hosted in a COM+ Application. Make sure that security permissions for the LegacyEventsFacade.dll file (or it's containing folder) allow read/execute access for the Network Service account (IIS application pool and Service Host run under it).

How to configure:

Example snippet from Tridion.ContentManager.config: all TOM.NET publishing events will trigger equivalent Legacy events and TOM.NET Keyword save events will trigger Legacy Keyword save event

    <section name="LegacyEventAdapter" type="Tridion.ContentManager.Extensibility.Events.LegacyEventAdapter.Configuration.LegacyEventAdapterConfiguration, Tridion.ContentManager.Extensibility.Events.LegacyEventAdapter, Version=, Culture=neutral, PublicKeyToken=621fa8382fc65733" />
 <!-- ... other configSection entries ... -->
  <!-- .. other configuration elements ... -->
      <clear />
      <add itemType="Tridion.ContentManager.CommunicationManagement.Page">
          <add type="Tridion.ContentManager.Extensibility.Events.LegacyEventAdapter.Resolver.LegacyResolverPreEventAdapter" assembly="Tridion.ContentManager.Extensibility.Events.LegacyEventAdapter, Version=, culture=neutral, PublicKeyToken=621fa8382fc65733" />
          <add type="Tridion.ContentManager.Publishing.Resolving.PageResolver" assembly="Tridion.ContentManager.Publishing, Version=, Culture=neutral, PublicKeyToken=360aac4d3354074b" />
          <!-- .. other page resolvers ... -->
          <add type="Tridion.ContentManager.Extensibility.Events.LegacyEventAdapter.Resolver.LegacyResolverPostEventAdapter" assembly="Tridion.ContentManager.Extensibility.Events.LegacyEventAdapter, Version=, culture=neutral, PublicKeyToken=621fa8382fc65733" />
      <!-- .. other mappings ... -->
    <add assemblyName="Tridion.ContentManager.Extensibility.Events.LegacyEventAdapter, Version=, culture=neutral, PublicKeyToken=621fa8382fc65733" />
 <!-- .. other extensions ... -->
  <LegacyEventAdapter legacyPublishingEventsEnabled="true" legacyKeywordSaveEventsEnabled="true" />

In the configuration sample you can see that there is a LegacyEventAdapter section which contains two boolean value attributes legacyPublishingEventsEnabled and legacyKeywordSaveEventsEnabled. The two attributes correspond to the events grouped under the section "What it does" in this readme.

Enabling or disabling a group can be performed by setting the attribute value to either "true" or "false". However, configuring the Resolving Events is a bit more tricky. They need to be configured in the "resolving\mapping" section in the configuration file. There are actually two resolvers that needs to be configured LegacyResolverPreEventAdapter and LegacyResolverPostEventAdapter corresponding to the Pre and Post resolving events of TOM. In order for this to work, the LegacyResolverPreEventAdapter needs to be the first resolver configured and LegacyResolverPostEventAdapter should be the last resolver configured.

This configuration needs to be repeated for all the item types that need the legacy events to be fired. The above sample shows how to do that for page.

Known issues:

  • The tcm:PublishResponse xml that will be available in *PublishPost events, can contain tcm:PublisherRequest and tcm:PublishScheduled elements. The tcm:PublisherRequest element will not contain the attributes TransactionNumber and PublishTransactionID, the tcm:PublishScheduled element will not contain the attribute PublishTransactionID.

  • Performance of the *PublishPost events will not be optimal as it will try to resolve Publication Targets again to be able to construct the tcm:PublishResponse xml. If needed - you can change the source code to skip this action if this information is not needed by your event handlers. 

  • The code block is contained in the .NET project "Tridion.ContentManager.Extensibility.Events.LegacyEventAdapter" and in the method "LegacyEventAdapter.CreateLegacyPublishResponse()". Looking at the code you can determine what information is needed by your event handler and comment/remove the rest.

  • For both the *ResolvePre and *ResolvePost events any changes done on the resolve items list in Legacy Event Handler is not going to be actually reflected back on the resolved items collection. Note that this was the behavior in SDL Tridion 2009.

  • In the legacy event handler if the passed in TOM object is used with tomSubject.GetXML(TDSDefines.XMLReadFilter.XmlReadAll) might result in an exception. As this object is actually being pre-loaded using the XML and some items might not have all the sections. For example, Keyword does not have Permissions xml section. So if GetXML operation is being performed on the TOM object it needs to be verified that the element actually exists for that item.

:    Bart Koopman
License agreement
Download package
:    legacy,  2011,  event system,  .NET,  adapter
:   1.0
:   Yes

About the Author
Bart Koopman
Community Development Consultant

As a Community Development Consultant, Bart is the evangelist of all SDL Tridion products. Bart used to be a consultant and trainer at SDL Tridion, supporting both partners and customers with their implementations.

SDL CMT division