Adding Fields To The Link Database

February 14, 2013

This article details how to add fields to the Link Database, how Sitecore uses the FieldTypes.config to add items to the Link Database, issues with the DelimitedField type and how to create your own custom type to use in the FieldTypes.config.

Adding Fields to the Link Database

Setting up new or custom fields is pretty straight forward. In my initial research I found this article by John West to be quite helpful. There's two parts to getting a field setup with the link db: setting up the config entries and rebuilding the link db. You can add entries to the FieldTypes.config file or your own custom config file if you've got one setup. The config entries are laid out like this:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">	<sitecore> 		<fieldTypes> 			<fieldType name="Field Name" type="Namespace.Class, BinaryName" /> 		</fieldTypes> 	</sitecore> </configuration> 

Then you've got to rebuild the Link Database by going into the Sitecore 'start' menu and opening up the control panel. Select the 'Database' section and then click on the 'Rebuild the Link Database' option. You'll get to pick which databases to run against. Typically you'll want to choose 'Master' or 'Web'. This will go through your content tree and check all fields so it may take a while. It may also fail so be prepared for that. Future incremental changes to the field entries will be handled by events defined in the Sitecore config.

How Sitecore uses the FieldTypes.config

The config entry has two attributes: 'name' and 'type'. The 'name' value should match your field name since it will be used to tell Sitecore which fields it should handle. The 'type' value on the other hand doesn't have to match your class. The 'type' does have a few requirements that aren't detailed anywhere I'm aware of. I'll list them below and explain in more detail after. The 'type' is used largely to reflect how the value is stored, not how is displayed. Based on all existing sitecore types it appears this 'type' should be a subclass of the Sitecore.Data.Fields.CustomField. The field also needs to have a constructor that takes a parameter whose type is Sitecore.Data.Fields.Field. This class will also need override and implement the CustomField's ValidateLinks method since it is an empty method.

So to better explain how Sitecore is using this config definition to add the field to the Link Database let's use the item:saved event. When you edit, for example, a Treelist field, and click the save button, the value is stored as a pipe delimited list of item ids. This event also triggers the item:saved pipeline event. By default, Sitecore's FieldTypes.config uses a Sitecore.Data.Fields.MultilistField to manage the Treelist field. This first calls the method Sitecore.Links.ItemEventHandler.OnItemSaved. It begins by using the Sitecore.Links.ItemLinks class to loop through all the fields on the item you're saving and checks to see if each field has an entry in the FieldTypes.config. With those that do, the entry from the config is used to create an object of the type specified with a constructor that takes a single Sitecore.Data.Fields.Field argument by way of the Sitecore.Reflection.ReflectionUtil. If the field provided doesn't have a constructor that matches that condition, it will be skipped. After the list of fields is compiled they are looped through again and their ValidateLinks method is called. This method will add the links it finds to a list that will be then added to the Link Database.

Some Issues with the Sitecore.Data.Fields.DelimitedField

While I was working to get the Field Suite fields added to the Link Database, I attempted to use the existing FieldTypes.config entries. For example I used the Sitecore.Data.Fields.MultilistField for the Field Suite Treelist since it was used for the Sitecore Treelist field. What I found when I began debuggging was that when I had set the source field for the Field Suite Treelist it would not be added to the link db. I pinpointed the issue being the definition for the Sitecore.Data.Fields.DelimitedField.GetDatabase() method. The logic checks the 'Source' field for a 'DataSource'. If that is found it will also try to find the 'Databasename' from the 'Source' field which makes sense. The problem is that if it doesn't find a 'Databasename' it fails to fallback on the default InnerField.Database value. It will instead return null even though there is a valid value to return. The only way to work around this is to extend the Delimited Field and override the ValidateLinks and GetDatabase methods and return the InnerField.Datbase by default. I later found an article by Alex Shyba that details this workaround. I've also submitted a support ticket to sitecore to let them know of the issue so it'll likely be patched in future releases.

Adding a Custom Type to the FieldType.config

Since I'm currently using the Field Suite fields and I needed to patch the previous issue so I began looking into the fields that Sitecore was using. I ended up building two classes to support the fields: IDField and IDListField. For the IDField I researched how the Sitecore.Data.Fields.ReferenceField and LookupField worked since they both managed fields that stored a single item id as a string. For the IDListField I researched the Sitecore.Data.Fields.Multilist and DelimitedFields. I largely used what I found in both sets of classes and trimmed out what I didn't need and simplified their logic. There are really only a few things that your custom class will need which I've explained above but want to reiterate:

  • It should be a subclass of the Sitecore.Data.Fields.CustomField class.
  • It should override the CustomField ValidateLinks method.
  • It should have a constructor that takes a Sitecore.Data.Fields.Field object as an argument.