How To Create a Publishing Page in SharePoint Online Using CSOM API

I am working on some provisioning code for SharePoint Online, and I needed to create a publishing page.  After some digging into the CSOM API, here is the code for adding a publishing page in SharePoint Online.

image

using (ClientContext ctx = Login(parentURL))
{
     try
     {
         var web = ctx.Web;
         ctx.Load(web);


        PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(ctx, web);
         ctx.Load(publishingWeb);


        if (publishingWeb != null)
         {
             string pageLayoutDisplayName = “ArticleLeft”;
             // Get Publishing Page Layouts
             List publishingLayouts = ctx.Site.RootWeb.Lists.GetByTitle(“Master Page Gallery”);
             ListItemCollection allItems = publishingLayouts.GetItems(CamlQuery.CreateAllItemsQuery());


            ctx.Load(allItems, items => items.Include(item => item.DisplayName).Where(obj => obj.DisplayName == pageLayoutDisplayName));
             ctx.ExecuteQuery();


            ListItem layout = allItems.Where(x => x.DisplayName == pageLayoutDisplayName).FirstOrDefault();
             ctx.Load(layout);


            List pages = ctx.Site.RootWeb.Lists.GetByTitle(“Pages”);
            
             PublishingPageInformation publishingPageInfo = new PublishingPageInformation();
             publishingPageInfo.Name = “test.aspx”;
             publishingPageInfo.PageLayoutListItem = layout;
            
             PublishingPage publishingPage = publishingWeb.AddPublishingPage(publishingPageInfo);


            List publishPageParentList = publishingPage.ListItem.ParentList;
             ctx.Load(publishPageParentList, list => list.EnableModeration);
             ctx.ExecuteQuery();


            publishingPage.ListItem[“PublishingPageContent”] = “test”;
             publishingPage.ListItem.Update();
             publishingPage.ListItem.File.CheckIn(string.Empty, CheckinType.MajorCheckIn);
             publishingPage.ListItem.File.Publish(string.Empty);


             if (publishingPage.ListItem.ParentList.EnableModeration)
                 publishingPage.ListItem.File.Approve(string.Empty);


            ctx.Load(publishingPage);
             ctx.Load(publishingPage.ListItem.File, obj => obj.ServerRelativeUrl);
             ctx.ExecuteQuery();


        }

public ClientContext Login(string URL)
         {
             SecureString passWord = new SecureString();
             foreach (char c in Password.ToCharArray()) passWord.AppendChar(c);
             ClientContext tenantContext = new ClientContext(URL);
             tenantContext.Credentials = new SharePointOnlineCredentials(Username, passWord);
             return tenantContext;
         }


A couple key notes for those interested:

  • Publishing pages require a page layout – in this case “ArticleLeft”.  The publishing page object is looking for the actual list item representing the page layout which requires you finding it and providing it.  This is what the first few lines of code are doing – looking up by Display Name the page layout for ArticleLeft.
  • In order to approve a page, content approval has to be turned on in the list.  If it’s not turned on and you run the “publishingPage.ListItem.File.Approve” method it will generate an exception.  You can check for it being turned on using the “EnableModeration” property.
  • Like most properties in CSOM, you have to explicitly load properties.  If you try to access the property and it hasn’t been loaded you will get an exception.  This is what the line “
  • ctx.Load(publishPageParentList, list => list.EnableModeration);” is doing – it’s requesting that property be explicitly loaded.

  • The pagename property is ithe physical name of the page and it has to end in “.aspx” or you will get an exception.
  • Once you have created the page, you can then set the content of the various fields within the page as well.  In this case, I successfully updated the field “PublishingPageContent” (which is the main content box in the ArticleLeft page template) with the string “test”.  This would allow you to inject any content into those boxes.

I haven’t tested it but I expect that this would also work in SharePoint 2013/2016 on premise as well.

Read More