Getting the root PageReference of the imported pages in Episerver

In our work to automate export and import of the production database into our test environment we had to maintain a test node in the Episerver page tree. This ment that we had to export it before replacing the database, and then import it again. Please see Exporting Episerver content programmatically through an ApiController and Importing Episerver content programmatically through an ApiController for information about this.

In order for our export functionality to know the node to export, we had to maintain information about its whereabouts. We keep this data stored in a PageReference property on our settings page. However, when the test node has been imported into our new database, we would need to update this property with a reference to the new content.

The code below has been simplified to reduce noise.

public class ImportExportService
{
  private readonly IContentRepository _contentRepository;

  public ImportExportService(IContentRepository contentRepository)
  {
    _contentRepository = contentRepository ?? throw new ArgumentNullException(nameof(contentRepository));
  }

  // ...

  internal void ContentImported_UpdateTestNodeReference(ITransferContext transferContext, ContentImportedEventArgs e)
  {
    // CopiedContentLink will only be same as ContentLink once, when the test node root page is imported.
    if (transferContext.CopiedContentLink != e.ContentLink)
    {
      return;
    }

    SettingsPage settings = // Get the settings page
    var clone = settings.CreateWritableClone();
    clone.TestNodeRoot = transferContext.CopiedContentLink;
    _ = _contentRepository.Save((PageData)clone, SaveAction.Publish, AccessLevel.NoAccess);
  }

There is an event called ContentImported which is fired everytime a content is imported by the IDataImport.Import method and this is the event that we would need to handle. Above we have added an event handler to our ImportExportService which is intended to update our settings page property.

The CopiedContentLink in the ITransferContext is the reference to the top page of the imported content. The currently imported page on the other hand is described in the ContentImportedEventArgs. By comparing ContentReferences from these two we can avoid setting the property once for every page being imported.

When the handler is done, we just need to add it to the event.

[InitializableModule]
[ModuleDependency(typeof(ServiceContainerInitialization))]
public class TestNodeImportInitializer : IConfigurableModule
{
  public void ConfigureContainer(ServiceConfigurationContext context)
  {
    _ = context ?? throw new ArgumentNullException(nameof(context));
    _ = context.Services.AddSingleton<ImportExportService, ImportExportService>();
  }

  public void Initialize(InitializationEngine context)
  {
    ImportExportService importExportService = ServiceLocator.Current.GetInstance<ImportExportService>();
    IDataImportEvents dataImportEvents = ServiceLocator.Current.GetInstance<IDataImportEvents>();
    dataImportEvents.ContentImported += importExportService.ContentImported_UpdateTestNodeReference;
  }

  public void Uninitialize(InitializationEngine context)
  {
    ImportExportService importExportService = ServiceLocator.Current.GetInstance<ImportExportService>();
    IDataImportEvents dataImportEvents = ServiceLocator.Current.GetInstance<IDataImportEvents>();
    dataImportEvents.ContentImported -= importExportService.ContentImported_UpdateTestNodeReference;
  }
}