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.

  1. Exported pages from EPiServer 4 and ran Fredrik Haglund's Decryption tool for EPiServer 4 Export Packages on my .epi4 file.
  2. 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.

Added Wednesday 13 March 2013 14:19 — Tags for this page: Episerver, ASP.NET

Comments

  1. Arild Henrichsen Thursday 14 March 2013 12:12

    That's a nice and quick way to do it!

    I'm assuming you already had a pagetype in your EPi7 site that matches the properties from the old pagetype, as the pagetype definition is not included in your import job?

    Also, your import does not handle Page Files. Not a requirement?

    I recently had to do approx. the same. Ended up exporting from 4.62 and importing in 6 R2 (tabs, pagetypes and pages). Worked like a charm, but then again these were pretty simple pagetypes with no xforms or dynamic properties.

    I haven't tried this, but I'd guess that another approach to getting content from 4 to 7 would be to export from 4, import into a clean 6 R2, then upgrade that to 7. From there your page(type)s are in the 7 format and you should be able to move them to another 7-site if you want. (Yes, involves quite a bit of export/import, but no coding necessary)

  2. Author Comment Thursday 14 March 2013 18:54

    Thanks Arild!

    Page types existed already and were only a match with the 4.6 site "in spirit". This way made it easy to re-map the properties needed.

    I didn't need to migrate any files.

    We didn't have hands-on access to the 4.6 environment so just getting a fresh DB backup was a hassle that this approach got rid of.

    In other migrations (to earlier versions) I've done something similar to what you describe lastly but often also using "Convert Pages" to re-map properties to current flavor of the newer project.

  3. Rupali Monday 18 November 2013 10:58

    How I can import or export properties with custom settings.

Add Your Comment