Custom properties
Shows how to implement a custom property by selecting a suitable base type.
Most common Optimizely Content Management System (CMS) property types have built-in persisting and rendering support. In most cases, you should not need to create custom properties. You can change the editorial experience without creating a custom property. However, if you need a custom property, select a proper base type from which you can inherit, depending on your data type. You can also create a template for the data type (if you want the property to be visible on templates).
When defining a custom property:
PropertyDefinitionTypePlugInAttributeis now sealed and cannot be inherited.- Use
PropertyDefinitionTypeAttributevia composition to register your custom property. - For types directly inheriting from
PropertyData, you must specify theDataTypeproperty.
Use ContentReference<T> for typed references
ContentReference<T> for typed referencesContentReference<T> lets you store references to a specific content type. Using the generic type ensures compile-time safety and better clarity when the property is bound to a known content type.
For example:
public IEnumerable<ContentReference<MyPageType>> LinkedPages { get; set; }The following example shows how to implement a custom property by selecting a suitable base type (for example, PropertyString, PropertyNumber); a property holds an enumerable of ContentReference and stores it as a serialized string.
[PropertyDefinitionType]
public class LinkingProperty: PropertyLongString {
public IEnumerable<ContentReference> LinkedReferences {
get {
if (!String.IsNullOrEmpty(LongString)) {
var entries = LongString.Split(';');
return entries.Select(e => ContentReference.Parse(e));
}
return null;
}
set {
LongString = String.Join(";", value.Select(r => r.ToString()));
}
}
public override object Value {
get {
return LinkedReferences;
}
set {
IEnumerable<ContentReference> links = value as IEnumerable<ContentReference>;
if (links != null) {
LinkedReferences = links;
} else {
base.Value = value;
}
}
}
public override Type PropertyValueType {
get {
return typeof (IEnumerable<ContentReference>);
}
}
public override object SaveData() {
return LongString;
}
}PropertyDefinitionType for blocks
PropertyDefinitionType for blocksWhen creating properties for blocks, use the common PropertyDefinitionType. The block type is now defined using PropertyDefinition.ItemTypeReference, rather than directly on the property type.
For example:
[PropertyDefinitionType]
public class BlockLinkingProperty : PropertyContentReference
{
public ItemTypeReference BlockType { get; set; }
}
NoteThis standardizes block references across CMS 13 and allows consistent binding in the Visual Builder.
Index references to other content from a custom property
If the custom property stores references to other content instances, you should also have a "soft" link indexer for the type. In that case, when an editor tries to delete a content item, a warning displays if a property on another content item holds a reference to the item to be deleted. If the custom property is inheriting PropertyContentReference, PropertyUrl, or PropertyXhtmlString, then the soft indexing is handled by the base type indexer. The following example shows a soft link indexer for the previous custom property above:
[ServiceConfiguration(typeof (IPropertySoftLinkIndexer))]
public class LinkingPropertyIndexer: IPropertySoftLinkIndexer<IEnumerable<ContentReference>> {
public IEnumerable<SoftLink> ResolveReferences(IEnumerable<ContentReference> propertyValue, IContent owner) {
var softLinks = new List<SoftLink> ();
foreach(var link in propertyValue) {
var softLink = new SoftLink {
OwnerContentLink = owner.ContentLink.ToReferenceWithoutVersion(),
OwnerLanguage = (owner as ILocalizable)?.Language,
ReferencedContentLink = link,
SoftLinkType = ReferenceType.PageLinkReference
};
softLinks.Add(softLink);
}
return softLinks;
}
}The indexer is registered with the IOC container for the IPropertySoftLinkIndexer interface, which implements the generic IPropertySoftLinkIndexer<T> interface where the generic argument is the PropertyValueType for the property implementation.
Updated 15 days ago
