Content model properties can be defined both as single value types (f.e. string) and as collection-based types (f.e. List<string>). In the back office, this usually results in a property editor displaying either a single input field or a (sortable) list of input fields.

Collection types

You can use either a collection interface or a concrete class for collection-based properties.

Interface

If you're defining a property with a collection interface, its value will be set with an instance of List<T>. Therefore, the interface that you use must be implemented by List<T> by the Redakt runtime. Additionally, it must be ICollection<T> or IReadOnlyCollection<T> or derived thereof. This further includes IList<T> and IReadOnlyList<T>IEnumerable<T> is not supported for collection-based properties.

We recommend using IReadOnlyList<T> for collection-based properties, to signal read-only intent.

Concrete class

For concrete classes, the type must implement IList<T>, and have a parameterless constructor. This includes many standard .NET collection types. Redakt uses the interface's Add() method to add items to the collection, therefore the collection must be mutable (i.e. no ReadOnlyCollection<T> or ImmutableList<T>).

Switching between single and collection-based types

You can freely switch your content model property definitions between single and collection-based types, without causing data-related errors in the system. In the database, property values are always saved as a collection, regardless of the CLR type.

Note: the first time a content item is saved after switching from a collection to a single type, property values will be truncated to the first value in the collection and any extra values will be discarded. As long as content has not been saved, you can switch back to a collection-based type without loss of data.