Episerver CMS Content Migration

In this post, I will cover how I was able to programmatically migrate content from a non-Epi CMS to an empty Episerver website. The trick is to generate a JSON file of all your web content from the previous CMS and programmatically push these to Epi.

High level, here are the steps I took:

  1. I prepared the assets in the file system in the structure I wanted them to be uploaded in Epi (i.e. files are located in the correct folders/hierarchy)
  2. I developed a tool that, when given a file path, will read the contents and upload the files programmatically into the Episerver Assets. Tool discussed here.
  3. I produced (a Java dev did it for me as the previous CMS was Java-based) a JSON export file of the contents of the previous CMS
  4. I created an Epi Admin plugin that can read the JSON export file and use the Episerver API to programmatically create the pages/blocks

The assets migration needed to happen first to make sure the programmatically created pages/blocks will properly refer to the correct existing assets (i.e. using ContentReference properties)

The sample code below uses JSON. The file on step 3 should look something like this:

CMS Content source

What the fourth tool needs to do is recursively parse the JSON file and based on the “Type”, it will create the relevant Episerver page type. Thanks to Episerver API.

The heart of this tool is this recursive method below.

private ContentReference GetOrCreatePage<T>
(JObject jsonPage, ContentReference parentPageReference) 
where T : PageData
   // check if page exists...
   var existingPage = ContentRepository.Service.GetChildren<T>(parentPageReference)
      .FirstOrDefault(c => c.Name == (string)jsonPage["Name"]);

   ContentReference pageReference;
   if (existingPage == null) {
      var newPage = ContentRepository.Service.GetDefault<T>(parentPageReference);
      pageReference = ContentRepository.Service.Save(newPage, SaveAction.SkipValidation);
   } else {
      pageReference = existingPage.ContentLink;

   // Populate content
   PopulateContent(pageReference, jsonPage);

   // Iterate through child pages and recursively get or create
   foreach (var childPage in (JArray)jsonPage["Children"]) {
      GetOrCreatePage((JObject)childPage, pageReference);

   return pageReference;

You will also need helper methods such as getting content reference based on url:

private ContentReference GetContentReferenceForUrl(string url) {
   return UrlResolver.Service.Route(new UrlBuilder(url))?.ContentLink;

I also have a method that takes care of updating/creating a block for a page:

private void UpdateOrCreateBlockForPage<T>(string blockName, JObject jsonBlock, ContentReference parentLink, ContentArea contentArea) 
where T : BlockData {
   // check if block exists on page
   var assetFolder = ContentAssetHelper.Service.GetOrCreateAssetFolder(parentLink);
   var existingBlock = ContentRepository.Service.GetChildren<T>(assetFolderForPage.ContentLink)
      .FirstOrDefault(b => (b as IContent).Name == blockName);

   ContentReference blockReference;
   if (existingBlock == null) {
      var newBlock = ContentRepository.Service.GetDefault<T>(assetFolderForPage.ContentLink);
      (newBlock as IContent).Name = blockName;
      blockReference = ContentRepository.Service.Save(newBlock as IContent, SaveAction.SkipValidation);
      if (contentArea == null) contentArea = new ContentArea();
      contentArea.Items.Add(new ContentAreaItem {
         ContentLink = (existingBlock as IContent).ContentLink
    } else {
      blockReference = existingBlock.ContentLink;

    // update content
    PopulateContentForBlock(blockReference, jsonBlock);


That’s pretty much it. Hope you get the flow!

If you get stuck/have questions, post a comment below or email me on [email protected]

Appreciate a comment if this has helped you in anyway!




Add a Comment

Your email address will not be published. Required fields are marked *