Office 365: Create Publishing Pages from XML
Applies To
- Office 365
- SharePoint 2007
- SharePoint 2010
Scenario
We are researching a move from SharePoint 2007 to SharePoint Online. Regarding moving the actual content (publishing pages) options seems to be limited especially with regard to migrating towards using managed metadata columns. So what we wanted is the ability to read from an XML file and create publishing pages through sandboxed code. The sandboxed code can be deployed to SharePoint online and the xml can be created by custom farm-level code on the SharePoint 2007 farm.
Solution
The blog article Publishing in sandboxed solutions - Create a page contains the main code behind the sandboxed visual webpart that I created. The webpart depends on a pages.xml file that is the only file in the SiteCollectionDocuments folder (hey, this is only a Proof of Concept!). See below for the contents of the XML file and the code for the webpart.
I used the Visual webpart template in VS2012, set to sandbox solution for developing the webpart. This should work similarly in VS2010 with the Power tools extension installed.
Here's what to do once you have the solution available:
- Put pages.xml as the only file in the SiteCollectionDocuments folder of a publishing portal
- Deploy sandboxed solution to site
- Put CreatePages webpart on a webpart page
- Push the button and see if a page is created correctly in the Pages library of the root web
The XML
<?xml version="1.0" encoding="UTF-8" ?>
<Pages>
<Page>
<Name>PageFromXML.aspx</Name>
<Title>Page created from XML file</Title>
<PageLayout>/_catalogs/masterpage/ArticleLeft.aspx, ArticleLeft</PageLayout>
<PageContent>Page created from XML file</PageContent>
</Page>
</Pages>
The Code
using Microsoft.SharePoint;
using System;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Web.UI.WebControls.WebParts;
using System.Xml;
namespace CreatePages.VisualWebPart1
{
[ToolboxItemAttribute(false)]
public partial class VisualWebPart1 : WebPart
{
// Uncomment the following SecurityPermission attribute only when doing Performance Profiling using
// the Instrumentation method, and then remove the SecurityPermission attribute when the code is ready
// for production. Because the SecurityPermission attribute bypasses the security check for callers of
// your constructor, it's not recommended for production purposes.
// [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Assert, UnmanagedCode = true)]
public VisualWebPart1()
{
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
InitializeControl();
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnCreatePage_Click(object sender, EventArgs e)
{
SPFile aXmlFile= GetXmlFile();
XmlDocument aXMLDoc = new XmlDocument();
byte[] bytes = aXmlFile.OpenBinary();
Stream aMemStream = new MemoryStream(bytes);
aXMLDoc.Load(aMemStream);
XmlNode aPageNameNode = aXMLDoc.SelectSingleNode("Pages/Page/Name");
XmlNode aTitleNode = aXMLDoc.SelectSingleNode("Pages/Page/Title");
XmlNode aPageLayoutNode = aXMLDoc.SelectSingleNode("Pages/Page/PageLayout");
XmlNode aPageContentNode = aXMLDoc.SelectSingleNode("Pages/Page/PageContent");
string aPageName = aPageNameNode.InnerText;
string aPageTitle = aTitleNode.InnerText;
string aPageLayout = SPContext.Current.Site.Url + aPageLayoutNode.InnerText;
string aPageContent = aPageContentNode.InnerText;
SPList aPagesList = SPContext.Current.Site.RootWeb.Lists["Pages"];
PublishingPageCreator.AddPublishingPage(aPageName, aPageTitle, aPageLayout, aPagesList.RootFolder, aPageContent);
}
private SPFile GetXmlFile()
{
SPFolder aSiteColDocsFolder = SPContext.Current.Site.RootWeb.Folders["SiteCollectionDocuments"];
SPFile afile = aSiteColDocsFolder.Files[0];
return afile;
}
internal static class CompiledTemplateStrings
{
internal static string templateRedirectionPageMarkup = @"<%@ Page Inherits='Microsoft.SharePoint.Publishing.TemplateRedirectionPage, Microsoft.SharePoint.Publishing,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c' %><%@ Reference VirtualPath='~TemplatePageUrl' %> <%@ Reference VirtualPath='~masterurl/custom.master' %>";
}
internal class PublishingPageCreator
{
private static byte[] pageAsBytes;
private static readonly UTF8Encoding PageEncoder = new UTF8Encoding();
internal static byte[] GeneratePageStreamAsBytes()
{
if (pageAsBytes == null)
{
byte[] bytes = PageEncoder.GetBytes(CompiledTemplateStrings.templateRedirectionPageMarkup);
pageAsBytes = new byte[bytes.Length + 3];
pageAsBytes[0] = 0xef;
pageAsBytes[1] = 0xbb;
pageAsBytes[2] = 0xbf;
bytes.CopyTo(pageAsBytes, 3);
}
return pageAsBytes;
}
internal static SPListItem AddPublishingPage(string name, string title, string layout, SPFolder folder, string aPageContent)
{
SPFileCollection files = folder.Files;
byte[] file = GeneratePageStreamAsBytes();
SPFile newFile = files.Add(name, file);
SPListItem item = newFile.Item;
item["ContentType"] = "HRSContentPage";
item["ContentTypeId"] = "0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3905";
item["PublishingPageLayout"] = layout;
item["PublishingPageContent"] = aPageContent;
item["Title"] = title;
item.Update();
newFile.CheckIn(string.Empty, SPCheckinType.MajorCheckIn);
return item;
}
}
}
}