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:
<p class="lead">The company you never knew you needed.</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?
@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:
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.
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.
<div class="jumbotron">
<h1>We've got sweet locations</h1>
<p>They're pretty much the hottest thing you'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>