I recently built a publishing solution for a client that is deployed as a sandbox solution on Office 365. It was a fairly typical publishing solution containing master pages, page layouts, web parts, and other assets. Content production (putting words and media on pages) took place after deployment of this solution, but we had an initial site map. Therefore the solution built the site with a feature event receiver that created subsites, added blank publishing pages with custom page layouts, and configured navigation.
In a farm based deployment the creation of a publishing page is easy thanks to members of the Microsoft.SharePoint.Publishing assembly like AddPublishingPage method of the PublishingWeb class. Unfortunately the Microsoft.SharePoint.Publishing assembly is not available in the sandbox. Fortunately, the contents of the assembly are not obfuscated and I was able to use ILSpy to understand and recreate AddPublishingPage in my own assembly.
First I need a string that represents the new page's markup.
internal static class CompiledTemplateStrings
internal static string templateRedirectionPageMarkup =
@"<%@ Page Inherits='Microsoft.SharePoint.Publishing.TemplateRedirectionPage,
<%@ Reference VirtualPath='~TemplatePageUrl' %> <%@ Reference VirtualPath='~masterurl/custom.master' %>";
Then I need a class that creates a new SPFile from an array of bytes that represent the page content. Once created, the code sets the appropriate properties to make the new page an Article Page content type and set the PublishingPageLayout and Title. Finally, the file is checked in and approved.
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 = 0xef;
pageAsBytes = 0xbb;
pageAsBytes = 0xbf;
internal static SPListItem AddPublishingPage(string name, string title, string layout, SPFolder folder)
SPFileCollection files = folder.Files;
byte file = GeneratePageStreamAsBytes();
SPFile newFile = files.Add(name, file);
SPListItem item = newFile.Item;
item["ContentType"] = "Article Page";
item["ContentTypeId"] = "0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900242457EFB8B24247815D688C526CD44D";
item["PublishingPageLayout"] = layout;
item["Title"] = title;
item.ModerationInformation.Status = SPModerationStatusType.Approved;
Invoke AddPublishingPage as follows:
PublishingPageCreator.AddPublishingPage(pageName, "Page Title", rootWeb.Url + @"/_catalogs/masterpage/MyPageLayout.aspx, My Page Layout", pages.RootFolder);
Use your target site's Url as rootWeb.Url. pages is an SPList instance of the Pages library.
You can read about an alternative approach using a module element in this excellent post: http://stefan-stanev-sharepoint-blog.blogspot.com/2010/07/provision-publishing-pages-in-sandbox.html
Author: Doug Ware