Sitecore

Customize Item Serialization for version control

By September 2, 2015 No Comments

In this article I will show another useful and great functionality from Sitecore: serialization of items having specific templates, on Save action.

The idea behind this post is that you might have some sensitive configuration or settings items, for which you would like to keep track of changes made or for version control.

The first step would be to create a new settings item, where to select the templates for items you want to keep serialized.

serialization-settings

You can put something in the source of the Treelist like:

datasource=/sitecore/templates&includetemplatesforselection=Template  

This will show items to select just under /Templates, and will allow users to select only *Templates *items, and nothing else.

Next, we need to define our own handler for the Save event, in Web.config:

<event name="item:saved">  
   ...
   <handler type="Custom.Serialization.SaveSerializationByTemplate, Custom.Serialization" method="OnItemSaved"/>
</event>  

The type of the handler needs to be the class, followed by the assembly name, and the method attribute is the enter point for the event.

Here is the code for the method:

using Sitecore.Data;  
using Sitecore.Data.Items;  
using Sitecore.Events;  
using System;  
using Sitecore.Data.Serialization;  
using Sitecore.Diagnostics;  
using Sitecore;

namespace Custom.Serialization  
{
    public class SaveSerializationByTemplate
    {
        private const string TEMPLATES_TO_SERIALIZE_FIELD_NAME = "Templates To Serialize";
        private const string SERIALIZATION_SETTINGS_PATH = "/sitecore/content/Settings/serialization-settings";

        public void OnItemSaved(object sender, EventArgs args)
        {
            Item currentItem = SitecoreEventArgs.GetItem(args, 0);
            if (currentItem == null || currentItem.TemplateID.IsNull)
            {
                return;
            }

            Item serializationSettings = Context.ContentDatabase.GetItem(SERIALIZATION_SETTINGS_PATH);

            if (serializationSettings != null && !string.IsNullOrEmpty(serializationSettings[TEMPLATES_TO_SERIALIZE_FIELD_NAME])
                && serializationSettings[TEMPLATES_TO_SERIALIZE_FIELD_NAME].Contains(currentItem.TemplateID.ToString()))
            {
                Log.Info("Serialization started for: " + currentItem.Paths.FullPath, this);
                ShadowWriter.PutItem(Operation.Updated, currentItem, currentItem.Parent);
            }
        }

    }
}

In the EventArgs, Sitecore sends us the current item for which the Save is made. Then, I am getting the Serialization settings item from the content database (master), and check if the template of the current item is found within the selected ones from the settings item.

If found, I am logging the operation and writing the item path, then* call the Serialization method*.

The result is that under the serialization folder, Sitecore will create a .item file, where the serialized version of the Item will be found.

The root folder for Serialization is defined in Web.config:

<!--  SERIALIZATION FOLDER  
      Points to the root of serialized databases tree (when using serialization functionality). Default value: $(dataFolder)/serialization
      -->
<setting name="SerializationFolder" value="$(dataFolder)/serialization" />  

and can be changed to point to a custom folder.

There are some further benefits we can achieve from this functionality. We could have an external monitoring tool on that folder, and when a change happens, automatically put the new changes to our Version Control System. This way, we will have a track of all the changes made, and easily be able to revert to one of them.

The “Revert” command can be called from the “Developer” option in the Ribbon:

revert-item

When this is called, Sitecore checks in the Serialization location, in the above example being:

serializationmastersitecorecontentHomeall-fields.item

and if the file is found, it will apply these rules: It will adjust the item to have the versions & values from the file, and changes from the database that aren’t found in the file, will be removed. (extra versions, different field values).

It is important to keep in mind that by using this option, we can have some data-loss.

Another option would be to hit the “Update” button, instead of Revert.

With Update, the behavior changes, as Sitecore will try to fetch any versions from the file that aren’t in the database, and add them if that’s the case. If a version exists both in the file and in the database, Sitecore will overwrite it only if the date in the “Updated” field in the file is newer than the one from the database.

Another difference between Revert and Update is that when using the last one, Sitecore won’t overwrite the “Item name”, “Template ID”, “Origin ID” and “Parent ID” fields of the item.

Having the big picture in mind, there are also some improvements that can be done to the code: since the event is firing on every Save of an item to check against its template, we can store the Serialization Settings item in a Custom Sitecore Cache, and improve the performance for the behavior, as I will show in a future post.

Nonetheless, there’s no need for limiting just to the “Save” event for this. Maybe we want to add the serialization for a “item:versionRemoved” or even an “item:deleting” event, just keep your mind open about it :)

This is all, hope you find the functionality useful.

Adrian Iorgu

Author Adrian Iorgu

Results-oriented and self-motivated lead engineer with a focus on delivering high-quality code and products in high traffic environments. Sitecore MVP 2016 & 2017

More posts by Adrian Iorgu

Leave a Reply