We are currently wanting to change a property from a XhtmlString to a ContentArea.
We are planning to rename the existing property and create the new ContentArea property in its place.
We are then hoping to migrate the old data into the new property (creating a content block, copying the XhtmlString into the block, adding the content block into the ContentArea).
Is it possible to do this migration of the old data into the new property in a MigrationStep? The only examples of MigrationSteps I have seen () only rename properties and don't show what to do with the data. I have seen one blog (Run Once Migration Step For Use With Commerce 14 | Optimizely Dev) that does more than just rename in a migration step, but it is for Commerce 14 rather than CMS.
I haven't personally tried using Migration step so can't comment on it.
However, another approach could be a simple onpublish event that gets data from the XML string, creates a new content block with the XHtml value and adds it to the content area before save. You can then create a scheduled job that publishes all content of that type.
I don't see why you couldn't move the old data using a MigrationStep, it's just a mechanism to run the code you need. Given the MigrationStep runs every time on initialisation, you'll need to add logic to ensure the data migration code runs once only.
Otherwise, a scheduled job as suggested by Aniket is also a good approach.
There is no one quick solution here. Assuming you have old PropertyA (XhtmlString), you want to move it to PropertyB (XhtmlString), and PropertyA as ContentArea instead. I would imagine what you can do
You can create a MigrationStep class for the purposes of ensuring the migration of content takes place, however you will need to leverage the different repositories in that method instead. In which case you could create a new Rich Text Block owned by the page, clone the XHtmlString from the old property to the Rich Text Block and then update the Content Area on the page to reference the new rich text block.
public class ContentUpdateMigrationStep : MigrationStep
public override void AddChanges()
var contentTypeRepository = ServiceLocator.Current.GetInstance<IContentTypeRepository>();
// You can also find the contentType definition by passing in new Guid("original-guid-string") if you have removed the content type
var targetContentType = contentTypeRepository.Load(typeof(MyContentType));
protected void UpdateInstances(ContentType contentType)
if (contentType == null)
var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
var contentModelUsage = ServiceLocator.Current.GetInstance<IContentModelUsage>();
var usages = contentModelUsage.ListContentOfContentType(contentType);
foreach (var contentUsage in usages)
// Perform content updates here with the IContentRepository
catch (Exception exception)
// Log something here