Converting IContent to IPublishedContent in Umbraco v8+
Tags: umbraco, csharp
Published: 2021-02-03 13:48:36

Within [Umbraco](https://www.umbraco.com), 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 `ContentService`.

[**TL;DR:** Just show me the solution!](#the-solution)

## The Problem

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 `IContent` and `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 `IPublishedContent`.

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 `IContent` to `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.

## The Research

### Strike 1

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)](https://our.umbraco.com/forum/extending-umbraco-and-using-the-api/77358-convert-icontent-to-ipublishedcontent), where the accepted answer [points to a Gist by Jeroen Breuer](https://gist.github.com/jbreuer/dde3605035179c34b7287850c45cb8c9) in which he creates an `IContent` extension method that wraps the `IContent` instance in a custom `IPublishedContent` implementation that does all the relevant conversions.

**PERFECT!**

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.

### Strike 2

As my search continued, I noticed that David Peck had recently tweeted asking the very same question.

{% twitter 1354496193859088394 %}

Could this be the answer?

Nope again!

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 `IContent` to `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 `PagePublishedContent` implementation

https://github.com/umbraco/Umbraco-CMS/blob/0bd4dced0b3e9205660114406b7e814f817179c7/src/Umbraco.Web/Macros/PublishedContentHashtableConverter.cs#L181

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** 🎉

## The Solution

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.

{% gist https://gist.github.com/mattbrailsford/5f9638d357df59aeac1be8588a06c31e %}

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

## 🚨 DISCLAIMER 🚨

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.