Episerver CMS Content Migration

I will cover how to automate content migration into an Epi website from a non-Epi CMS. Yes, you read that right. You can automate migration of content into Epi from another CMS and save yourselves the time and money required for a manual data-entry.

Even if your content is currently stored in a Java-based CMS, PHP-based CMS, it can be done. As long as you (or your devs) have access to your current non-Epi CMS database and can perform queries to, then it is doable.

If you are a non-technical person who has a technical resource willing to build it for you, then you can stop here and forward this blog entry to them. You’re welcome.

If you are a non-technical person who doesn’t have a technical resource to do it, then PM me on info@nicolaayan.com

If you are a technical person, then the below post is for you. High level, here are the steps you need to take:

  1. Prepare the  assets in your file system in the structure you want them to be uploaded in Epi.
  2. Develop 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. Create a JSON/XML export file from your current non-Epi CMS
  4. Create an Epi plugin that can understand the JSON/XML export file and use the Episerver API to programmatically create your pages/blocks

The assets migration has to happen first so when you’re ready to migrate content, your pages/blocks can 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 info@nicolaayan.com

Appreciate a comment if this has helped you in anyway!




Leave a Reply

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