Getting Started with Contentful rich text and .NET
Pre-requisites
This tutorial assumes you understand the basic Contentful data model as described in the developer center and that you have already read and understand the getting started tutorial for the .NET client library.
Contentful.net is built on .NET Core and targets .NET Standard 2.0. The client library is cross-platform and runs on Linux, macOS and Windows.
What is rich text?
Rich text is a new JSON format for handling complex content structures in a strongly typed manner. It is represented by the rich text field in Contentful.
Working with a rich text property in the Contentful .NET client library
Create a property in your model class of type Document.
The Document class contains a list of IContent which contains all the nodes of your rich text field deserialized into strongly typed classes. When you’ve fetched your entry that contains the rich text field you can iterate through this collection and use pattern matching to decide which action to take depending on the type of node.
The most common use case is that you need to convert your rich text into HTML. The .NET client library provides the HtmlRenderer class to facilitate this.
The html variable will now contain an HTML string representation of the content. The HtmlRenderer contains a list of renderers that can handle all of the node types that exist natively in the Contentful web app, except entries. If you wish to render entries or other custom node types you need to write your own IContentRenderer and add it to the HtmlRenderer via the AddRenderer method. The following is an example of a custom renderer that will render any embedded-entry-block.
This custom renderer can now be added to the HtmlRenderer.
Note that the Order of the renderer is set to 10 to make sure it is added earlier in the rendering pipeline. The default order of the standard renderers are 100, except for the NullContentRenderer which has a default order of 500.
Working with a rich text property in an ASP.NET Core application
If you’re working with ASP.NET Core the HtmlRenderer gets injected into the dependency injection pipeline and is available once you run services.AddContentful(Configuration) in your startup.cs.
There’s also a tag helper that you can use directly in your Razor files to render a Document property to HTML.
The tag helper will use the configured HtmlRenderer to render the provided Document directly to HTML.
To use custom taghelpers they need to be imported. Add @addTagHelper *, Contentful.AspNetCore to the \_ViewImports.cshtml
If you have custom nodetypes or need to render entries, some additional setup is required to add the custom renderers to the HtmlRenderer pipeline.
It’s important to add any custom renderers after your services.AddContentful(Configuration) call and not before.
If you want your custom renderer to render a .cshtml view you can let your custom renderer inherit from the RazorContentRenderer. This gives your renderer the RenderToString method which takes the name of a view and a model to pass to the view.
As there are some services required to render a .cshtml view you also need to update the creation of the renderer in your startup.cs file.
Working with custom node types
If you have completely custom node types in your structure you will need to pattern match on the CustomNode type or write a custom renderer that handles the CustomNode type.
A renderer to handle a custom node would also need to handle the CustomNode type and then deserialize the JObject into an appropriate type.
If you want to inject your custom renderer into the HtmlRenderer available out of the box you also need to make sure the serialization engine knows how to deserialize your content type into a c# class. This is done by implementing an IContentTypeResolver and instructing the engine which type a certain content type would correspond to. Here is an example.
This resolver then needs to be set on the client before fetching content.
The classes you expect to be part of a rich text structure must also implement the IContent interface. This means that any class you setup with the IContentTypeResolver should also ideally implement the IContent interface, which is a simple marker interface used to identify parts of a rich text structure.