3

I am attempting to hook into the Tridion Event System to insert a component's WebDAV URL into a MetaData field on that component during the save process. I have been led to understand that the WebDAVUrl is the best identifier to use for a Tridion element since it maintains a consistent value across environments when ported (we cannot rely on the Tridion id to be the same when content is ported). Also, since dynamic components are not published with the WebDAV URL as metadata by default like other elements, we must find a way to dynamically insert these values.

The issue I am having is that when hooking into the Save Event of the Event System for components on the EventPhases.Initiated phase, the component WebDAV URL is not reflective of any title changes that have occurred on the component.

Here is my sample custom Event Hook, based on sample code provide here: Performance Counters Example

using System;
using Tridion.ContentManager.ContentManagement;
using Tridion.ContentManager.ContentManagement.Fields;
using Tridion.ContentManager.Extensibility;
using Tridion.ContentManager.Extensibility.Events;

namespace com.TridionEvents
{
    [TcmExtension("Tridion2011EventSystemRC")]  // This needs to be unique per Event System
    public class EventSystem : TcmExtension
    {
        public EventSystem()
        {
            Subscribe();
        }

        public void Subscribe()
        {
            // OnComponentSavePre
            EventSystem.Subscribe<Component, SaveEventArgs>(OnComponentSavePre, EventPhases.Initiated);

        }

        private static void OnComponentSavePre(Component comp, SaveEventArgs args, EventPhases phase)
        {        
            String title = comp.Title; //This is a new title and should be part of the new WebDAV URL

            ItemFields metadataFields = new ItemFields(comp.Metadata, comp.Schema);
            EmbeddedSchemaField schemaField = (EmbeddedSchemaField)metadataFields["WebDAVPath"];
            SingleLineTextField webDavText = (SingleLineTextField) schemaField.Values[0]["WebDAV"];
            webDavText.Value = comp.WebDavUrl; // Here the comp.WebDavUrl is not reflective of the new title and what the WebDavUrl actually will become, post save.
            comp.Metadata = metadataFields.ToXml();

            args.ContextVariables.Add("StartTime", DateTime.Now);
        }
    }
}

I have configured the custom event system correctly, and I am able to debug, and see that what I am trying to accomplish is actually working, with the exception that the WebDavUrl is not updated.

For example, on a newly created component with the title "Foo", the WebDavUrl at this point will still be something like: "/some/path/New%20Component.xml"

If I go back and change the title of the component to: "Bar", the WebDavUrl at this point will be something like: "/some/path/Foo.xml", reflective of the previous state of the component.

I presume this may have something to do with the fact that component WebDavUrl is not resolved until after the component has been successfully saved.

My questions then are:

  • Is there some way of getting the newest WebDAVUrl in the pre-save phase?
  • Is there some other event phase that can give me this information and allow me to save it into component metadata?
  • Is there some other way outside of the event system that can accomplish the same thing (while still allowing me to query the Content Delivery API for this component by the WebDAV URL)?

The integration scenario being worked through here is highly dynamic in nature, so the options being put forward by user978511 and Nick have already been discounted (not that we would dispute their validity for other scenarios).

Coming back to the question at hand at little further experimentation finds that the updated WebDAV URL for the Component is only available at Processed. (That it is not available at Initiated seems a little counterintuitive - one would not expect to get the old version of the content at Initiated, for example.)

Referring back to Bart's primer on SDL Tridion 2011 .NET events, that seems to suggest that generating the WebDAV URL is part of the magic sauce of the second step in the event life cycle ("CMS action takes place (not a phase)"). Perhaps someone more intimately familiar with the underlying code might be able to confirm this?

Following that line of thinking, I was wondering about the code that generates the WebDAV URL for items in the Content Manager:

  • Is the code that generates the URL wrapped up in its own API anywhere?
  • If yes, would it be accessible through the Core Service (broadly thinking: GUI extension + some obscure API call = win)?
3

It seems that the reason you want a WebDAV URL on the delivery side is so you can query for this component without having to hardcode the Tcm Id into your CD code. However as user978511 pointed out you'll run into issues.

The typical way to handle the scenario you describe is to keep the environment-specific attributes in a config file, just like db connection settings, and other standard things you add to config that vary between dev, QA and prod. Tcm IDs fall into the same category - each environment has their own.

Another common approach is to publish out the config file from the CM. Create a "config" schema/component and a corresponding CT/PT to render it. In your component set up your mapping of MY_QUERYABLE_COMPONENT=component link (I.e. Tcm id).

2

Your approach is not entirely correct. It's true that you will not get the proper WebDAV url until component is saved, but you also can't be sure that url you have in metadata is correct at the time of publishing, let's say component is moved, in this scenario it will not be updated.

Better approach will be to do something during publishing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.