Umbraco Html.RichTextFor: Rendering Rich Text Editor HTML

A lot of times you want to render HTML as entered by the user through Umbraco’s rich text editor. This works right out of the box if you are using the standard View API: the dynamic model knows what to do if the property contains a macro or internal link.

However, if you are using a strongly typed view, this fact that the field came from a rich text editor is lost: outputting the field value directly, even with Html.Raw will not always work. Any macros or internal links will be outputted as the raw internal codes that Umbraco uses to designate the use of those features.

For example, I have a demo site with a Macro for outputting a Bootstrap jumbotron. But if I just use Html.Raw(Model.Body) in my template, I get:

View Source
1
2
3
4
<p class="lead">The company you never knew you needed.</p>
<?UMBRACO_MACRO macroAlias="JumbotronMacro" headline="We&#x27;ve got sweet locations" tagline="They&#x27;re pretty much the hottest thing you&#x27;ve ever seen." buttonText="Go check them out." buttonLink="1077" />
<h2>Example body text</h2>
<p><span>Nullam quis risus eget <a href="/{localLink:1085}" title="Privacy Policy">fdkfl;sdfk</a></span><span> vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam id dolor id nibh ultricies vehicula.</span></p>
  • Theres an UMBRACO_MACRO element containing macro parameters as attributes.
  • Theres a link with an href of {localLink:1085}. This is an internal link to another page on the site. Umbraco encodes the link using it’s ID so that if you change the name, it can properly generate the new URL.

Helpfully, there are a couple library functions you can use to parse those fields and translate into the correct HTML: umbraco.library.RenderMacroContent and TemplateUtilities.ParseInternalLinks.

It’s tedious to remember to use them each time, so wouldn’t it be nice to wrap that up into a helper so you can just do this?

View.cshtml
1
2
3
4
5
@model BlogPost
<div class="user-content">
@Html.RichTextFor(m => m.Body);
</div>

It assumes you have a sane model hierarchy where every model extends from a base class with the Umbraco Id property on it:

Models.cs
1
2
3
4
5
6
7
8
9
10
public class BaseDocument
{
public int Id { get; set; }
}
public class BlogPost : BaseDocument
{
// Will hold HTML from rich text editor
public string Body { get; set; }
}

Since we need that Umbraco ID to call RenderMacroContent, the helper method is generically constrained to subclasses of BaseDocument. You could also use an interface or just pass the ID in as a parameter.

HtmlHelperExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
public static class HtmlHelperExtensions
{
public static MvcHtmlString RichTextFor<T>(this HtmlHelper<T> helper, Func<T, string> property) where T : BaseDocument
{
var model = helper.ViewData.Model;
var richText = property(model);
var withMacros = umbraco.library.RenderMacroContent(richText, model.Id);
var withLinks = TemplateUtilities.ParseInternalLinks(withMacros);
return MvcHtmlString.Create(withLinks);
}
}

Now it properly renders the macro and resolves the link to document 1085.

View Source
1
2
3
4
5
6
7
<div class="jumbotron">
<h1>We&#39;ve got sweet locations</h1>
<p>They&#39;re pretty much the hottest thing you&#39;ve ever seen.</p>
<p><a class="btn btn-primary btn-lg" href="/locations/">Go check them out.</a></p>
</div>
<h2>Example body text</h2>
<p><span>Nullam quis risus eget <a href="/privacy-policy/" title="Privacy Policy">fdkfl;sdfk</a></span><span> vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam id dolor id nibh ultricies vehicula.</span></p>