Dynamic content items
Many times during the development of an ECM project the need arises to have content items whose set of fields (not just the value of each field) can be modified individually on a per-instance basis. There might be many reasons for this:
- Set of fields is unknown at development time
- Set of fields changes so often that changing them in a CTD would lead to a maintenance overhead
- Each instance contains different data and this would lead to having to create too many CTDs
- You want to expose user-added data as fields on a content item (for example, this would give you the ability to modify this data through OData)
The solution to this problem is to create dynamic content items. This involves creating a custom content type for which you specify that its instances will be able to add new fields on the fly.
Creating dynamic content items
This is a three-step process.
- 1. Create a custom content type with your own content handler
- 2. Implement the ISupportsAddingFieldsOnTheFly interface with your content handler
- 3. Take care of exposing the on-the-fly-added fields, by, for example, implementing ISupportsDynamicFields
You have to take care of the following:
- Storage of dynamic fields - Implement this in the ISupportsAddingFieldsOnTheFly.AddFields method. You could, for example, use a binary field and serialize data into it, or use an external data source.
- Exposing the dynamic fields - You will have to make the Content Repository aware of your dynamic field. This can be done in ISupportsDynamicFields.GetDynamicFieldMetadata, for example.
- Exposing values of the dynamic fields - Allow the Content Repository to get and set the values of your dynamic fields. You can do this by overriding the GetProperty and SetProperty methods in your content handler.
There are two notable examples currently in Sense/Net that utilize this feature:
- Settings - all setting values are exposed as dynamic fields so you can easily interact with them through OData and the built-in UI
- DynamicJsonContent - example content item, similar to Settings but simpler. Feel free to study its code!
Several convenient APIs have been developed to ease the process of creating dynamic content items.
JsonDynamicFieldHelper is a class that helps the storage of dynamic fields in a Sense/Net binary field, serialized as JSON. The DynamicJsonContent example uses this class.
It helps you with
- Building dynamic field metadata by determining the appropriate Field Setting type for JSON properties
- Implementing GetProperty and SetProperty over a JSON object
Note: this class also exposes nested JSON objects as fields whose names are separated by dots.
These handy static methods help with dynamic field creation:
- InferFieldSettingFromType(Type type, string fieldName) - tells you which of the built-in Field Setting types can handle the given .NET type, or returns null if none is suitable.
- InferFieldSettingFromString(string fieldValueInString, string fieldName) - tells you which of the built-in Field Setting types can handle the given string value, or returns null if none is suitable. Checks if the string contains a number, decimal value, bool, etc.
- InferFieldSettingFromXml(XmlNode fieldValueInXml, string fieldName) - tells you which of the built-in Field Setting types can handle the given XML fragment, or returns null if none is suitable. (This method is also called by the import tool.)
Consuming dynamic content items
Accessing the dynamic fields
You can use and access the dynamic fields, just like you would any other field. They are available on the Content level in the .NET API, and they can be manipulated through OData just like any other field.
Creating new dynamic fields
The Content API has a method called AddFieldsOnTheFly which you can use to add new fields to your dynamic content items.
If you save a dynamic content item through OData, all the fields that don't exist yet on the content item but you specify in the HTTP request body will be created automatically.
If you import a dynamic content item using the import tool, all the fields that don't exist yet on the content item but you specify in the .Content file will be created automatically.