In my previous post about ECL, I’ve discussed querying ECL Metadata in the Broker, by making it available as part of the Multimedia (stub) Component Metadata. Now in that post I explained how it could be copied at Publishing time and the “evil” twists that process came with. In this post I’ll discuss an optional approach, using the SDL Tridion Event System which makes the process of copying external metadata to (normal) metadata less evil (just the process, not the fact that we do it ;o).
To begin with, the Template Building Block which I wrote for my previous post, had the downside of needing to update a Component while it was being Published (with all the security implications that brings). It came to my attention this approach could mean the data was added just a fraction to late, requiring the ECL Component to be published again to get the metadata in the Broker. As a solution I went looking for alternatives and started playing around with the SDL Tridion event handlers.
Initially I had not considered an event handler, because it would have to be triggered on Component Save and then you need to filter out the ECL stub Components. But I think I came to a rather elegant solution of filtering out ECL stub Components belonging to a specific ECL provider only. More about that later, let me first explain the main approach.
So the task at hand is that we need to copy the value from an ECL external metadata field to the metadata of the ECL item (or ECL stub Component if you will, since from a metadata perspective they are the same). This ideally is done when the ECL stub Component is first created, and for that we can use the Event System. The available event triggers do not contain something specifically for ECL items, so we need to simply subscribe to the Component Save event, and filter out if the item being saved is an ECL stub Component and then perform our copy task.
Looking at the event handler code, first we need to know what ECL stubs we should react on. In the event handler constructor, (after reading configuration settings) I simply build up a list of all mountpoints of a certain type, so I can use that to filter out possible other ECL stub Components. Next it simply subscribes to the Component Save event, having an option to subscribe synchronously or asynchronously. The benefit of subscribing synchronously to the event is that you only need a single save and the update happens instantaneously. Since that comes with a performance impact, you could also opt for doing it asynchronously, which will create an additional version as the stub is saved again after creation (if the ECL stub Component creation is triggered by a publish action, we will need the synchronous action for it to be in time).
The actual event handler code is where the real “magic” happens of course, I start off with a quick inexpensive test to see if we are dealing with an ECL stub Component (see if the title starts with “ecl:” and if it is a Multimedia Component). If true, I create an ECL session and try to get the ECL URI from the subject.Id. If that exists we are dealing with an ECL stub Component and I can match it against my list of mountpoints. Now we know we are dealing with the right item, and we can start copying our metadata (I do test if the metadata field actually is allowed, since it could be missing in our Schema and it makes no sense to throw exceptions over that). The rest of the code (which actually compares and copies the value) is not really much different than that used in my Template Building Block.
This event handler can now be used as an alternative to the Template code, Deployer or Storage extension I discussed before. Less evil, but still it definitely can be improved by hiding or making these copied metadata fields read only, through a UI extension like the Tridion FBI extension (as discussed here).
As usual, the entire event handler is available as open source and downloadable for free on SDL Tridion World. It would be directly usable in combination with my Flickr ECL provider (copying the Description field), but I much rather suggest you to use it as example code to implement your own solution. Besides the handy way of identifying a ECL stub Component from a specific provider, it also contains a usable example of how you easily add configuration values to an event handler.
Great article Bart!
Note that there is one big difference with saving the component on publish time: in this event system you have to assume the external library metadata does not change. The stub component will only be saved at the first time the ECL item is saved, or when the user changes the metadata on the stub component. Having that said, I am not a huge fan of saving component during publish time either.
If you have a custom built provider, like the Flicker example provider, you could set the stub metadata in the provider itself instead of in this event system. The ECL API IContentLibraryContext.StubComponentCreated() is triggered when a new stub component is created and on that moment the provider could use the Core Service to update the stub component with metadata.
You hit the nail absolutely on the head Jan, in the end all of the solutions I could come up with have their own pros and cons.
Very good point about the
IContentLibraryContext.StubComponentCreated()
, when you create the provider code yourself or have the option to modify it, but you can’t edit the Tridion Component from there, since that is still being created (you would have to use the Core Service and generally speaking it isn’t good practice to use the Core Service inside your ECL provider).Hi.
Note that your “quick inexpensive test to see if we are dealing with an ECL stub Component” is probably a bit more expensive than you think it is: you use subject.Schema.Purpose, which (probably) causes a full load of the Schema.
There is a much less expensive way to test the same: subject.ComponentType == ComponentType.Multimedia.
Thanks Rick, I’ll update the code accordingly.
Google code seemed to have stopped their forwarding service too, the Google Code links should point to GitHub https://github.com/bkoopman/sdl-tridion-world/tree/master/ECL%20Stub%20Component%20Event%20Handler/trunk
Pingback: How to map ECL external metadata to your view model – Tim's Blog