Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Migrate Episerver Dynamic content to Episerver blocks
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.IO;
using david_tec.Models.Blocks;
using david_tec.Models.Pages;
using EPi.Blog.Templates.PlugIn;
using EPiServer;
using EPiServer.Core;
using EPiServer.Core.Html.StringParsing;
using EPiServer.PlugIn;
using EPiServer.Scheduler;
using EPiServer.Security;
namespace david_tec.Business.ScheduledJobs
[ScheduledPlugIn(DisplayName = "MigrateDynamicContentToBlocks")]
public class MigrateDynamicContentToBlocks : ScheduledJobBase
private bool _stopSignaled;
private readonly IContentRepository _contentRepository;
private readonly ContentAssetHelper _contentAssetHelper;
public MigrateDynamicContentToBlocks(IContentRepository contentRepository, ContentAssetHelper contentAssetHelper)
_contentRepository = contentRepository;
_contentAssetHelper = contentAssetHelper;
IsStoppable = true;
/// <summary>
/// Called when a user clicks on Stop for a manually started job, or when ASP.NET shuts down.
/// </summary>
public override void Stop() => _stopSignaled = true;
/// <summary>
/// Called when a scheduled job executes
/// </summary>
/// <returns>A status message to be stored in the database log and visible from admin mode</returns>
public override string Execute()
OnStatusChanged($"Starting execution of {this.GetType()}");
StringWriter sw = new StringWriter();
foreach (var contentId in GetContentToMigrate())
sw.Write(contentId + ",");
if (_stopSignaled)
return "Stop of job was called";
return "Page Ids updated: " + sw;
private void PlaceBlockOnPage(int contentId)
var originalPage = _contentRepository.Get<BlogPostPage>(new ContentReference(contentId)).CreateWritableClone() as BlogPostPage;
var updatedXhtmlString = originalPage.BodyText.ToInternalString();
var updateXhtml = false;
foreach (var bodyTextFragment in originalPage.BodyText.Fragments)
if (bodyTextFragment.GetType() == typeof(DynamicContentFragment))
// Get the original dynamic content values using the orignal DynamicContent control
// -- In this scenario we only CodeBrowserView is used so this is safe
var originalDyanamicContnet = (CodeBrowserView)((DynamicContentFragment) bodyTextFragment).DynamicContent;
var codeType = originalDyanamicContnet.Properties["Brush"].Value.ToString();
var codeSnippet = originalDyanamicContnet.Properties["CodeSnippet"].Value.ToString();
// Create a new block
var codeBlock = CreatePageLevelBlock(contentId, codeType, codeSnippet);
// Update the XHTML string to embed the block and remove the dynamic content reference
var embeddedBlock = "<div data-classid=\"36f4349b-8093-492b-b616-05d8964e4c89\" data-contentguid=\"" + (codeBlock as IContent).ContentGuid + "\" data-contentname=\"" + (codeBlock as IContent).Name + "\" class=\"epi-contentfragment mceNonEditable\" data-contentlink=\"" + (codeBlock as IContent).ContentLink.ID + "\">" + (codeBlock as IContent).Name + "</div>";
updatedXhtmlString = updatedXhtmlString.Replace(bodyTextFragment.InternalFormat, embeddedBlock);
updateXhtml = true;
if (updateXhtml)
originalPage.BodyText = new XhtmlString(updatedXhtmlString);
_contentRepository.Publish(originalPage, AccessLevel.NoAccess);
private IContent CreatePageLevelBlock(int contentId, string codeType, string codeSnippetText)
ContentAssetFolder folder = _contentAssetHelper.GetOrCreateAssetFolder(new ContentReference(contentId));
var codeSnippet = _contentRepository.GetDefault<CodeSnippet>(folder.ContentLink);
codeSnippet.CodeType = codeType;
codeSnippet.Code = codeSnippetText;
(codeSnippet as IContent).Name = contentId + "_Code";
_contentRepository.Publish(codeSnippet as IContent, AccessLevel.NoAccess);
return codeSnippet as IContent;
private IList<int> GetContentToMigrate()
var returnItems = new List<int>();
var query =
"SELECT [fkContentID] FROM [dbo].[tblContentProperty] WHERE LongString LIKE \'%data-dynamicclass%\' ORDER BY [fkContentID]";
using (SqlConnection cn =
new SqlConnection(ConfigurationManager.ConnectionStrings["EPiServerDB"].ConnectionString))
SqlCommand cmd = new SqlCommand(query, cn);
var reader = cmd.ExecuteReader();
while (reader.Read())
return returnItems;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment