Nat and I have worked together for quite a while now and Don’t Fight the Framework has become a running meme between us almost since day one.
In this post I thought I’d take a side step on this and talk about an example of going against best practise. Admittedly, best practise is often convention based so it can be hard to know what is the right and wrong way. As in many cases there is the right way and the better way, which is usually the case in Sitecore.
Before I continue, I want to point out that there is nothing wrong with creating event handlers for saved and published events. Running code from the rules engine, moving items, creating items etc are all good examples (and I use them). But you must be aware of the consequences and code accordingly. That said, they can also used for the wrong reasons as we will discover.
Item saved and Publish events
Being able to attach your own code to one of the many events raised by Sitecore offers up a wealth of opportunities to modify content, run custom code (pipelines and jobs if you’re know what you’re doing) and generally solve real world problems quickly and easily.
Usually, I see these done as saved events and publish events. These are also one of the biggest causes of confusion, resource wastage and publishing issues in an installation. Modifying or appending to these events requires a real understanding of the issues doing it raises which, for the sake of brevity, I will only discuss the following:
- Publish events raise multiple saved events on every item being published but you won’t know you’re publishing unless you subscribe to publish start events and write some flag somewhere (and remember to clear it) or look at the current job.
- Performing an action on saved is can be the wrong time to modify content, you should consider using the ‘saving’ event as an alternative.
- Performing an action on publish implies workflow (which can be progressed through without user interaction)
- Performing a conditional action on publish implies workflow
- Workflow supports security more easily and doesn’t require ‘magic fields’
- Performing a conditional action on save *may* be better done as workflow or in the SaveUI Pipeline. It really depends on your requirements.
- Its also worth considering that item:saved gets raised on create, update, rename and move as well across all databases :).
One example of using the item saved event is to auto populate a field based on the content of others (such as for SEO). This involves, usually, using a security disabler, creating an editing context and updating the item. Then you remember you need to disable events for your editing to avoid recursion. Then you add code to ensure if you’re already handling an event for this item you don’t do it again. Then you accept this will get called anyway on publish.
Alternatively, the item saving event gives us the ability to see what has changed in the document before and after and allows us to modify directly. We also have an editing context already. However, we do get called on publish so we’ll still need some guard code here just as with saved (unless we can use the SaveUI pipeline).
With all of this, lets build on the above with an example of using the tools Sitecore provides and using the framework rather than fighting against it.
Our requirement is to be able to publish a content item and, selectively, have it sent as an email on publish. Now straight away this sounds like a workflow problem to me. However, for the initial solution we shall use a checkbox on the content item that sends an email when checked. All triggered by the publish event.
So lets look at what’s wrong with this.
- It puts the burden of responsibility on anyone with write access to the item
- It puts a lot of power into that field that can be accidentally set
- It relies on the publish event to unset that field when the item is published
- Realistically the sending of an email and publishing minor updates are separate things or at least it should be easy to keep them separate.
Now consider that the item may already have save event handlers on it that potentially aren’t publish or database aware and that we’ve now hooked in a potentially long running process (which may fail) and then firing another save event at the end of each item and we can see it doesn’t scale.
One alternative is to consider these discrete steps as actions that occur at particular states of the item. We have an item that is either in the ready to publish state or in the ready to publish and send an email state. Our actions being publish and send email.
Out of the box we now have the means to publish via workflow (its shipped with the product) so all we need to do is create the additional workflow steps and the email action. If we need to manage the security we can customise our workflow using the API and create some custom roles. Simpler, works with Sitecore and much easier to test.
For more info, refer to the SDN on the workflow API.
So to summarise, its worth thinking about what tools Sitecore (or any CMS for that matter) provide out of the box and whether its a stretch to use them. In the sample provided it isn’t a stretch and makes for a better solution.
This article is part of the Don’t Fight The Framework Series
- Don’t fight the framework pt I – Introduction
- Don’t fight the framework pt III – Lucene and Other Tools
- Don’t fight the framework pt IV – Presentation
- Don’t fight the framework pt V – Sitecore’s built on Sitecore so build your solutions on Sitecore.