Docs > Content Management > Data Model Annotations >

Html

The [Html] data annotation can be used to decorate a string property and provides a UI hint to the admin interface to display an html editor field. Cofoundry uses the TinyMCE editor to edit html content.

public class ExampleDataModel : ICustomEntityDataModel
{
    [Html]
    public string? Content { get; set; }
}

Customizing the toolbar

The HtmlToolbarPreset enum defines a few preset toolbars that can be used to control the set of toolbars that are rendered with the html editor:

  • Headings: A style selector for h1-h3 headings and normal text.
  • BasicFormatting: Buttons for bold, italic, underline, links and clear formatting.
  • AdvancedFormatting: Buttons for alignment, blockquote & lists, strikethrough and superscript/subscript.
  • Media: Buttons to insert pictures, video
  • Source: Edit html source button.
  • Custom: Indicates the position to insert a custom toolbar (see below)

By default the Headings and BasicFormatting toolbars will be displayed. You can change the default by specifying them in the attribute constructor:

public class ExampleDataModel : ICustomEntityDataModel
{
    [Html(HtmlToolbarPreset.BasicFormatting, HtmlToolbarPreset.Media, HtmlToolbarPreset.Source)]
    public string? Content { get; set; }
}

Adding a custom toolbar

You can use the HtmlToolbarPreset.Custom enum value to insert a custom toolbar, and use the CustomToolbar property to define the buttons. You can see a full list of buttons in the TinyMCE toolbar documentation, and use the pipe separator to split toolbars.

In addition to the buttons included with TinyMCE, there is also a button for inserting images from the Cofoundry image library which you can reference with the keyword cfimage:

public class ExampleDataModel : ICustomEntityDataModel
{
    [Html(HtmlToolbarPreset.Custom, CustomToolbar = "undo redo | bold italic underline | link unlink | cfimage")]
    public string? Content { get; set; }
}

Editor height/rows

You can set the editor height using the Rows property, the same way you can with the [MultiLineText] attribute. The default is 20.

public class ExampleDataModel : ICustomEntityDataModel
{
    [Html(Rows=10)]
    public string? Content { get; set; }
}

Customizing the TinyMCE Config

You can completely control the configuration of TinyMCE by defining your own configuration. There ware two properties you can use to do this:

ConfigSource

A type to use to determine any additional configuration options to apply to the html editor. This should be a class that inherits from IHtmlEditorConfigSource, which provides a .NET code generated set of options.

public class ExampleHtmlEditorConfigSource : IHtmlEditorConfigSource
{
    private static readonly Dictionary<string, object> _options = new Dictionary<string, object>()
    {
        { "resize", false },
        { "browser_spellcheck", false }
    };

    public IDictionary<string, object> Create()
    {
        return _options;
    }
}

public class ExampleDataModel : ICustomEntityDataModel
{
    [Html(ConfigSource = typeof(ExampleHtmlEditorConfigSource))]
    public string Content { get; set; }
}

ConfigFilePath

You can also define a path to a JSON configuration file if you prefer to write your config in JSON:

html-editor-config.json

{
  "resize": false,
  "browser_spellcheck": false,
  "toolbar": "undo redo | bold italic underline | link unlink | preview forecolor backcolor",
  "plugins": "link preview textcolor",
}

ExampleDataModel.cs

public class ExampleDataModel : ICustomEntityDataModel
{
    [Html(ConfigFilePath = "/content/html-editor-config.json")]
    public string? Content { get; set; }
}

Escaping and Sanitizing

When working with html you need to be aware of two things:

1. Tiny MCE cleans HTML

TinyMCE will try and clean up any html and remove what it thinks are invalid or dangerous elements. If you have users pasting in code from other sources e.g. internet or document files, then this can be useful to keep the input clean, however this can be a problem if your inputting raw html snippets or JavaScript content.

To prevent TinyMCE from cleaning up code you can override the config to allow all elements:

public class AllowAllElementsHtmlEditorConfigSource : IHtmlEditorConfigSource
{
    public IReadOnlyDictionary<string, object> Create()
    {
        // configure TinyMCE to permit all elements
        return new Dictionary<string, object>() 
        {
            { "valid_elements", "+*[*]" }
        };
    }
}

public class ExampleDataModel : ICustomEntityDataModel
{
    [Html(ConfigSource = typeof(AllowAllElementsHtmlEditorConfigSource))]
    public string? Content { get; set; }
}

2. You should consider sanitizing when rendering HTML

Cofoundry includes a sanitizer than you can use to clean up HTML when rendering content and prevent XSS attacks.

Take a look at the sanitizer documentation for more information.

Custom html editor attributes

If you're using a specific configuration often, you may want to consider deriving a new data annotation from the base HtmlAttribute.

[AttributeUsage(AttributeTargets.Property)]
public class HtmlWithCustomEditorAttribute : HtmlAttribute
{
    public HtmlWithCustomEditorAttribute()
        : base(HtmlToolbarPreset.BasicFormatting, HtmlToolbarPreset.Media, HtmlToolbarPreset.Source)
    {
        ConfigFilePath = "/content/html-editor-config.json";
        Rows = 40;
    }
}

public class ExampleDataModel : ICustomEntityDataModel
{
    [HtmlWithCustomEditor]
    public string Content { get; set; }
}