One way to import pages from Episerver 4 to 7
I was given the task to import pages from Episerver 4.6 to a new Episerver 7 site. Access was limited and I had no possibility to modify the code or configuration of the 4.6 project. I went for a solution where an export package was used.
First I needed the XML of the decrypted export package.
- Exported pages from Episerver 4 and ran Fredrik Haglund's Decryption tool for Episerver 4 Export Packages on my .epi4 file.
- Unzip the decrypted file and open the Data file in text program to see if have some XML there, I also added .xml to the name.
I was only interested in some of the page types and only a selected few other properties so I created a generic class to put in between a XML RawPage and my new EPi 7 Page. This also helped me to keep track of the parent/child relationships in the Data file.
private class ImportItem
{
public int ID { get; set; }
public int ParentID { get; set; }
public int PageTypeID { get; set; }
public DateTime StartPublish { get; set; }
public string PageName { get; set; }
public Dictionary OtherProperties { get; set; }
public ContentReference NewContentReference { get; set; }
}
My Data XML file was massive in file size so I needed to use a XmlTextReader, to still be able to use XElement niceness I use ReadSubtree() for one page element at a time. In my case Import() is called from a Episerver Scheduled Task.
private string Import()
{
var all = new List<ImportItem>();
// TODO: Path to your Data file needs to be set
using (var reader = new XmlTextReader("file:///C:/Data.xml"))
{
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
if (reader.Name.Equals("RawPage"))
{
using (var pageReader = reader.ReadSubtree())
{
var rawPage = XElement.Load(pageReader);
var properties = rawPage.Descendants("RawProperty").ToList();
var otherProperties = new Dictionary();
foreach (var p in properties)
{
switch (p.Element("Name").Value)
{
case MetaDataProperties.PageChildOrderRule:
case MetaDataProperties.PagePeerOrder:
// Office
case "Name":
case "Address":
case "LegalName":
case "Phone":
case "Email":
case "OfficeID":
// Person
case "FirstName":
case "LastName":
case "Title":
case "WorkPhone":
case "WorkMobile":
case "PersonalPhone":
case "PersonalMobile":
case "Email":
if (p.Element("Value") != null
&& p.Element("Value").Value != null)
{
otherProperties.Add(
p.Element("Name").Value,
p.Element("Value").Value);
}
break;
}
}
all.Add(new ImportItem
{
PageTypeID = properties.Single(x => x.Element("Name")
.Value.Equals("PageTypeID")).Element("Value")
.Value.ToInt(),
ID = properties.Single(x => x.Element("Name")
.Value.Equals("PageLink")).Element("Value").Value.ToInt(),
ParentID = properties.Single(x => x.Element("Name")
.Value.Equals("PageParentLink")).Element("Value")
.Value.ToInt(),
StartPublish = properties.Single(x => x.Element("Name")
.Value.Equals("PageStartPublish")).Element("Value")
.Value.ToDateTime(),
PageName = properties.Single(x => x.Element("Name")
.Value.Equals("PageName")).Element("Value").Value,
OtherProperties = otherProperties
});
}
}
break;
}
}
}
var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
// TODO: Put the Export package starting point PageLink.ID here
var root = all.SingleOrDefault(x => x.ID == 318);
if (root != null)
{
// My EPi 7 starting point is added below the start page
var page = contentRepository.GetDefault(PageReference.StartPage);
page.PageName = root.PageName + " " + DateTime.Now;
page[MetaDataProperties.PageChildOrderRule] =
root.OtherProperties[MetaDataProperties.PageChildOrderRule];
page[MetaDataProperties.PagePeerOrder] =
root.OtherProperties[MetaDataProperties.PagePeerOrder];
root.NewContentReference = contentRepository.Save(
page, SaveAction.Publish, AccessLevel.NoAccess);
this.SaveChildren(ref contentRepository, root.ID, ref all);
}
return "Done.";
}
private void SaveChildren(ref IContentRepository contentRepository, int parentID, ref List all)
{
foreach (var ii in all.ToList().Where(x => x.ParentID == parentID))
{
// Fixed id's
var parent = this.GetParentReference(ii.ParentID, ref all);
if (parent != null)
{
// TODO: Your ID
if (ii.PageTypeID == 20)
{
// Office
var page = contentRepository.GetDefault<Office.Models.OfficePage>(parent);
page.PageName = ii.PageName;
page.VisibleInMenu = true;
page[MetaDataProperties.PageChildOrderRule] =
ii.OtherProperties[MetaDataProperties.PageChildOrderRule];
page[MetaDataProperties.PagePeerOrder] =
ii.OtherProperties[MetaDataProperties.PagePeerOrder];
// One example of other properties
if (ii.OtherProperties.ContainsKey("OfficeID"))
{
page.OfficeID = ii.OtherProperties["OfficeID"].ToInt();
}
ii.NewContentReference = contentRepository.Save(
page, SaveAction.Publish, AccessLevel.NoAccess);
}
// TODO: Your ID
if (ii.PageTypeID == 22)
{
// Person
var page = contentRepository.GetDefault<Models.AddressBookPersonPage>(parent);
page.PageName = ii.PageName;
page.VisibleInMenu = false;
page[MetaDataProperties.PageChildOrderRule] =
ii.OtherProperties[MetaDataProperties.PageChildOrderRule];
page[MetaDataProperties.PagePeerOrder] =
ii.OtherProperties[MetaDataProperties.PagePeerOrder];
// One example of other properties
if (ii.OtherProperties.ContainsKey("Title"))
{
page.Title = ii.OtherProperties["Title"];
}
ii.NewContentReference = contentRepository.Save(
page, SaveAction.Publish, AccessLevel.NoAccess);
}
if (ii.NewContentReference != null)
{
this.SaveChildren(ref contentRepository, ii.ID, ref all);
}
}
}
}
private ContentReference GetParentReference(int oldParentId, ref List all)
{
var list = all.ToList().Where(x => x.ID == oldParentId);
if (list.Any())
{
return list.First().NewContentReference;
}
return PageReference.WasteBasket;
}
Worked great in my case (30 000+ pages) and hopefully this way could be an option for someone else as well.
Published and tagged with these categories: Episerver, ASP.NET, Development