Declaring a content type

Declaring content types for basic persistence is straightforward, as the rules for this are part of the Entity Framework Code First documentation.

For content persistence, it is possible to use a wide range of types as a content model, subject to the following rules

  • The type can contain any primitive property
  • The type can contain standard .Net value typed properties like DateTime
  • The type cannot contain interface-typed properties or those of types which have subtypes (e.g. object)
  • The type can contain properties typed to other types which follow these rules
  • The type can inherit from other types with follow these rules
  • The type can contain a List<T> of a type which follows these rules
  • The type must be marked with SerializableAttribute, and therefore be binary serializable.  It also needs to be Json serializable.  If it follows the above rules, it should be serializable in both these ways.
  • When initialised, the type must not have any complex object or collection set to null; this can be conveniently be ensured by running BaseContent.InitialiseProperties(this) in the constructor.

Ideally the type will inherit directly or indirectly from BaseContent.  The primary advantage of this is that the type will then carry its metadata around: otherwise, if you wish to save it you will have to specify what content address to save it to.

By convention, content type names have the word Content added to the end to distinguish them.

See Predefined content subtypes for a list of the built-in subtypes Lynicon provides to help with common use cases in web content.

See Content type attributes for a list of the attributes which can be applied to content types and their properties

Example

The following is a typical example of a content type declaration:

[Serializable]
public class Block : Switchable
{
	[UIHint("Html")]
	public string Text { get; set; }
 
	[UIHint("Multiline")]
	public string Code { get; set; }
 
	public Image Image { get; set; }
 
	public Block()
	{
		Image = new Image();
	}
}
 
[Serializable]
public class ManualContent : PageContent
{
	[Summary, Index(IndexAttribute.Mode.TextualAndAgglomerated)]
	public string Title { get; set; }
 
	public List<Block> Body { get; set; }
 
	[JsonIgnore, ScaffoldColumn(false), Index(IndexAttribute.Mode.TextualAndAgglomerated)]
	public string BodyText
	{
		get
		{
			var sb = new StringBuilder();
			foreach (var b in Body)
			{
				sb.Append(" ");
				sb.Append(HttpUtility.HtmlDecode(b.Text.StripRegions("<", ">")));
			}
 
			return sb.ToString();
		}
	}
 
	public ManualContent()
	{
		BaseContent.InitialiseProperties(this);
	}
 
	List<Summary> manualIndex = null;
	public List<Summary> ManualIndex()
	{
		if (manualIndex == null)
		{
			manualIndex = Collator.Instance.Get<Summary, ManualContent>()
				.OrderBy(s => s.Url)
				.ToList();
		}
 
		return manualIndex;
	}
}
LinesDescription
1-16Here we have the declaration of a subtype to be used in the content type. This is an inheritor of Switchable.
4The UIHint attribute is used to ensure an HTML editor is used to enter the value which is stored in this string. This implies the string contains HTML and should be rendered in Razor using \@Html.Raw()
7The UIHint attribute is used to ensure a TextArea is used as the editor for this value.
14The constructor ensures that any object-typed properties are initialised to a newly constructed instance of the object.
1,18Any class used as a content type needs to be marked as Serializable
18-59Here is the content type itself. Note it inherits from PageContent which is a marker that it is the content for a whole page template, and it inherits common page-level properties like PageTitle
21Marks the Title property as being part of the Summary, also the IndexAttribute specifies that this property should be indexed for search
24Here we have a list of Blocks. The editor built from this, because Block is a Switchable, will let you decide whether each Block is Text, Code or an Image.
27This property is marked with JsonIgnore, ScaffoldColumn(false), which means it is ignored in persistence and the editor. It is used to get the text from all the blocks which have it, stripped of HTML
44BaseContent.InitialiseProperties(this) is a utility which automatically sets all object-valued properties to a newly default-constructor constructed instance of the object.
48A method is declared on the content type. This can be done freely to provide functionality to use when rendering the content type. In this case, it gets the summaries of all ManualContent items in the system.