Within Umbraco, content can be accessed in two possible ways, either via the
ContentService which returns
IContent or via the
ContentCache which returns
IPublishedContent. The main difference with these is that
IContent comes straight from the database, and all of it's properties are stored in a raw format, where as
IPublishedContent comes from a cache layer with all it's properties stored in a more accessible and strongly typed manor.
Generally speaking, when working with content in Umbraco, if you are reading / rendering content, you'll want to use
IPublishedContent from the
ContentCache, and if you are creating / updating content you'll want to use
IContent and the
There are times however when content may not yet be available in the
ContentCache, such as in a content Saving/Saved event handler, and so it would be great if, as a last resort, we could fallback to fetching the
IContent version from the database and use that instead.
The issue with this however is that
IPublishedContent are very different interfaces especially around content property access, where with
IContent you are generally dealing with a raw format, often JSON instead of the friendlier strongly typed access you get from
In these situations you need to do one of two things, either create code that works in two different ways depending on the model you are working with, but this often requires you to have insider knowledge as to how the raw properties are formatted, or, we can implement some kind of wrapper to convert the
IContent interface into
IPublishedContent and have all the contents properties converted to their strongly typed implementation in the same way that Umbraco does internally. The benefit of this approach is that we only have to write code that deals with one particular interface and we don't have to worry about the property raw data formats.
This then is the approach I decided to take.
In an ideal world, it would be great if Umbraco had an API that could do this for you out of the box, after all, it must be doing this already when it converts the
IPublishedContent in order to add it to the
ContentCache. Unfortunately however, this is not the case (not publicly anyway), and so we must go about implementing a solution ourselves.
Before taking a stab at this problem myself I thought I'd do a quick search to see if the problem had already been solved.
The first promising result I came across was a forum post on the Umbraco Developer Portal (Our), where the accepted answer points to a Gist by Jeroen Breuer in which he creates an
IContent extension method that wraps the
IContent instance in a custom
IPublishedContent implementation that does all the relevant conversions.
Not so fast!
Under closer inspection it appeared that it only seemed to work for Umbraco v7 installs and I needed a solution for Umbraco v8+ so unfortunately it wasn't a goer.
As my search continued, I noticed that David Peck had recently tweeted asking the very same question.
David PeckUmbraco Twitter: does anyone have any idea how I can convert IContent in to IPublishedContent in ContentService.Saving?
I want to trigger all the PropertyValueConverters.18:27 PM - 27 Jan 2021
Could this be the answer?
In the thread, David was basically discouraged from doing this, and really I can understand why as the whole point of the caching layer is to ensure the site stays performant and using
IContent instead of
IPublishedContent is one sure fire way of bringing a site to a halt if used improperly.
Regardless, if used properly, I still think being able convert
IPublishedContent is a useful feature in certain circumstances, so I continued with my quest.
At this point I started to poke around the Umbraco source code trying to find where it does it's own conversion, and that's when I came across the
PublishedContentHashtableConverter and specifically it's
The more I looked at it, the more I thought "This looks pretty close to Jeroen's code. Could I just update what Jeroen had and make it work for Umbraco v8? 🤔"
And so, I DID 🎉
What you'll find below then is essentially a cross between the code from Jeroen's original Gist and elements from the
PagePublishedContent in order to bring it inline with the Umbraco v8 API.
It may look like a lot of code, but ultimately all it's doing is taking an
IContent element, and wrapping it in an
IPublishedContent custom implementation that intercepts all of it's field / method requests and runs the same code Umbraco does during a conversion including property value conversion.
It does this in a Lazy way too meaning it should only run the expensive code if you ask for the given property, and once it's run, it remembers the result so it won't need to run the same code again.
For me this is exactly what I needed and given I knew at least one person was looking for an answer to the same problem, I thought I might as well throw it up on a blog post, and so here it is.
I hope this helps
I mentioned it a little previously, but working with
IContent is not the most performant way to work with Umbraco content, so if you do use this method, be sure to know what you are doing.
I won't be held responsible for any problems you introduce into your solution by using this. Use this code at your own risk.