How Does .NET Core Work with Headless CMS?

I am still in the experimental stage of my evaluation of both (SaaS) headless CMS and headless CMS with .NET Core. I think that Headless CMS should have minimal impact on .NET Core content delivery implementations. I also think that we’re doing all headless Content Management implementations wrong from an architectural perspective. I intend to suggest better architectures in the future and I would be glad to discuss those suggestions if you contact me directly (John West).

Headless CMS products expose RESTful APIs that .NET Core applications can invoke to alter data in and retrieve data from the CMS. ASP.NET web applications and .NET Core command line tools can use.NET SDK from the CMS vendors to retrieve objects of custom types with property values serialized from the JSON representations of Entries in the CMS or to work with the raw JSON from the CMS.

On the web client side, headless CMS implementations work well with the Jamstack, typically with clients such as browsers invoking RESTful API calls. You may choose to optimize this architecture with ASP.NET Core solutions. For example, rather than the client retrieving HTML from ASP.NET and then JSON from the CMS, the HTML that you generate can include the JSON representations of Entries needed for JavaScript in the page, where the application may have cached that JSON from a previous request. This approach can improve performance without the need to expose security tokens and other CMS vendor internals to the client.

On the web server side, you can use ASP.NET and headless CMS with minimal or no reliance on JavaScript. .NET Core applications can abstract the JSON representation of an Entry as an object called an Entry Model, which ASP.NET Core MVC applications can use as view models. You pass a type and an identifier or a query to the CMS SDK and it returns zero or more objects of that type representing the Entry or Entries that you requested with properties populated from the JSON representations of those items. If the number of Entries matched exceeds the limit defined by the CMS vendor, you may need to invoke the SDK to page through additional batches of Entries.

You can pass one or more identifiers, such as a Content Type identifier and Entry identifier, or a query, such as to locate the Entry with a matching value in its URL Field. You pass the Entry Model class that you want to use to the CMS API, which returns zero or more objects of that type with property values deserialized from the JSON.

The Entry Model(s) returned from the SDK may appear wrapped in a collection or enumeration/enumerator/collection within an object that provides information about the HTTP response to the RESTful API call, possibly including raw or modified JSON representation of the Entry from the CMS. An Entry Model may provide a property or method that exposes the raw or modified JSON.

Your goals as a .NET Core architect or developer working with headless CMS may include:

  • Minimize uses of CMS SDKs, direct invocations of RESTful APIs, vendor-specific query functionality, as well as reading and writing of JSON formats including GraphQL.
  • Centralize all CMS access in a code layer that all other projects can access with no awareness of or other dependence on the CMS or its SDK. Projects that contain Entry Model classes should have no code dependency on the CMS SDK and no logic specific to the CMS.
  • Where you must iterate Content Types and/or page through batches of Entries, consider using multiple threads. I have not run any diagnostics, but my subjective perspective from processing thousands of Entries repeatedly is that creating threads manually results in greater performance than using existing thread pools.
  • To optimize performance and minimize costs, when possible and at the cost of memory, cache raw JSON for deserialization to multiple Entry Models.
  • Ensure that publishing operations evict and/or clear both JSON and ASP.NET output caches, preferably not excessively.

One of your primary jobs as a .NET Core headless CMS developer is data modeling. Data modeling involves defining Content Types and the Entry Model classes (possibly in a class hierarchy) to model those Content Types, as well as the ways that Entries refer to other Entries. Contentful, Contentstack, and Kentico all provide tools to generate C# classes that you can use as Entry Models.

While Entry Models are invaluable, code generators have limitations and you should learn to code and maintain Entry Model classes by hand.

Especially with headless CMS offerings that define an Entry as a list of (potentially repeating) Fields, you will likely need to retrieve some (or all, although beware deep trees and recursion) additional Entries referenced in those Field Values, which presents particular coding challenges. You may experiment to determine whether your solution achieves greater performance by using CMS vendor APIs to inline referenced Entries into the JSON representation of an Entry or to retrieve each Entry separately. This decision could affect how your Entry Models represent referenced Entries.

Even if your solution benefits from caching the JSON representation of Entries, to optimize performance by avoiding RESTful transfer of data that the solution does not use, you may want to use techniques to explicitly include or exclude Fields retrieved from the CMS.

Leave a comment