Building Publishing Pages in Code
- by David Jacobus
Originally posted on: http://geekswithblogs.net/djacobus/archive/2013/10/27/154478.aspxOne of the Mantras we developers try to follow: Ensure that the solution package we deliver to the client is complete. We build Web Parts, Master Pages, Images, CSS files and other artifacts that we push to the client with a WSP (Solution Package) And then we have them finish the solution by building their site pages by adding the web parts to the site pages. I am a proponent that we, the developers, should minimize this time consuming work and build these site pages in code. I found a few blogs and some MSDN documentation but not really a complete solution that has all these artifacts working in one solution. What I am will discuss and provide a solution for is a package that has: 1. Master Page 2. Page Layout 3. Page Web Parts 4. Site Pages Most all done in code without the development team or the developers having to finish up the site building process spending a few hours or days completing the site! I am not implying that in Development we do this. In fact, we build these pages incrementally testing our web parts, etc. I am saying that the final action in our solution is that we take all these artifacts and add them to the site pages in code, the client then only needs to activate a few features and VIOLA their site appears!. I had a project that had me build 8 pages like this as part of the solution. In this blog post, I am taking a master page solution that I have called DJGreenMaster. On My Office 365 Development Site it looks like this: It is a generic master page for a SharePoint 2010 site Along with a three column layout. Centered with a footer that uses a SharePoint List and Web Part for the footer links. I use this master page a lot in my site development! Easy to change the color and site logo with a little CSS. I am going to add a few web parts for discussion purposes and then add these web parts to a site page in code. Lets look at the solution package for DJ Green Master as that will be the basis project for building the site pages: What you are seeing is a complete solution to add a Master Page to a site collection which contains: 1. Master Page Module which contains the Master Page and Page Layout 2. The Footer Module to add the Footer Web Part 3. Miscellaneous modules to add images, JQuery, CSS and subsite page 4. 3 features and two feature event receivers: a. DJGreenCSS, used to add the master page CSS file to Style Sheet Library and an Event Receiver to check it in. b. DJGreenMaster used to add the Master Page and Page Layout. In an Event Receiver change the master page to DJGreenMaster , create the footer list and check the files in. c. DJGreenMasterWebParts add the Footer Web Part to the site collection. I won’t go over the code for this as I will give it to you at the end of this blog post. I have discussed creating a list in code in a previous post. So what we have is the basis to begin what is germane to this discussion. I have the first two requirements completed. I need now to add page web parts and the build the pages in code. For the page web parts, I will use one downloaded from Codeplex which does not use a SharePoint custom list for simplicity: Weather Web Part and another downloaded from MSDN which is a SharePoint Custom Calendar Web Part, I had to add some functionality to make the events color coded to exceed the built-in 10 overlays using JQuery! Here is the solution with the added projects: Here is a screen shot of the Weather Web Part Deployed: Here is a screen shot of the Site Calendar with JQuery: Okay, Now we get to the final item: To create Publishing pages. We need to add a feature receiver to the DJGreenMaster project I will name it DJSitePages and also add a Event Receiver: We will build the page at the site collection level and all of the code necessary will be contained in the event receiver. Added a reference to the Microsoft.SharePoint.Publishing.dll contained in the ISAPI folder of the 14 Hive. First we will add some static methods from which we will call in our Event Receiver: 1: private static void checkOut(string pagename, PublishingPage p)
2: {
3: if (p.Name.Equals(pagename, StringComparison.InvariantCultureIgnoreCase))
4: {
5:
6: if (p.ListItem.File.CheckOutType == SPFile.SPCheckOutType.None)
7: {
8: p.CheckOut();
9: }
10:
11: if (p.ListItem.File.CheckOutType == SPFile.SPCheckOutType.Online)
12: {
13: p.CheckIn("initial");
14: p.CheckOut();
15: }
16: }
17: }
18: private static void checkin(PublishingPage p,PublishingWeb pw)
19: {
20: SPFile publishFile = p.ListItem.File;
21:
22: if (publishFile.CheckOutType != SPFile.SPCheckOutType.None)
23: {
24:
25: publishFile.CheckIn(
26:
27: "CheckedIn");
28:
29: publishFile.Publish(
30:
31: "published");
32: }
33: // In case of content approval, approve the file need to add
34: //pulishing site
35: if (pw.PagesList.EnableModeration)
36: {
37: publishFile.Approve("Initial");
38: }
39: publishFile.Update();
40: }
In a Publishing Site, CheckIn and CheckOut are required when dealing with pages in a publishing site. Okay lets look at the Feature Activated Event Receiver:
1: public override void FeatureActivated(SPFeatureReceiverProperties properties)
2: {
3:
4:
5:
6: object oParent = properties.Feature.Parent;
7:
8:
9:
10: if (properties.Feature.Parent is SPWeb)
11: {
12:
13: currentWeb = (SPWeb)oParent;
14:
15: currentSite = currentWeb.Site;
16:
17: }
18:
19: else
20: {
21:
22: currentSite = (SPSite)oParent;
23:
24: currentWeb = currentSite.RootWeb;
25:
26: }
27:
28:
29: //create the publishing pages
30: CreatePublishingPage(currentWeb, "Home.aspx", "ThreeColumnLayout.aspx","Home");
31: //CreatePublishingPage(currentWeb, "Dummy.aspx", "ThreeColumnLayout.aspx","Dummy");
32: }
Basically we are calling the method Create Publishing Page with parameters: Current Web, Name of the Page, The Page Layout, Title of the page. Let’s look at the Create Publishing Page method:
1:
2: private void CreatePublishingPage(SPWeb site, string pageName, string pageLayoutName, string title)
3: {
4: PublishingSite pubSiteCollection = new PublishingSite(site.Site);
5: PublishingWeb pubSite = null;
6: if (pubSiteCollection != null)
7: {
8: // Assign an object to the pubSite variable
9: if (PublishingWeb.IsPublishingWeb(site))
10: {
11: pubSite = PublishingWeb.GetPublishingWeb(site);
12: }
13: }
14: // Search for the page layout for creating the new page
15: PageLayout currentPageLayout = FindPageLayout(pubSiteCollection, pageLayoutName);
16: // Check or the Page Layout could be found in the collection
17: // if not (== null, return because the page has to be based on
18: // an excisting Page Layout
19: if (currentPageLayout == null)
20: {
21: return;
22: }
23:
24:
25: PublishingPageCollection pages = pubSite.GetPublishingPages();
26: foreach (PublishingPage p in pages)
27: {
28: //The page allready exists
29: if ((p.Name == pageName)) return;
30:
31: }
32:
33:
34:
35: PublishingPage newPage = pages.Add(pageName, currentPageLayout);
36: newPage.Description = pageName.Replace(".aspx", "");
37: // Here you can set some properties like:
38: newPage.IncludeInCurrentNavigation = true;
39: newPage.IncludeInGlobalNavigation = true;
40: newPage.Title = title;
41:
42:
43:
44:
45:
46:
47: //build the page
48:
49:
50: switch (pageName)
51: {
52: case "Homer.aspx":
53: checkOut("Courier.aspx", newPage);
54: BuildHomePage(site, newPage);
55: break;
56:
57:
58: default:
59: break;
60: }
61: // newPage.Update();
62: //Now we can checkin the newly created page to the “pages” library
63: checkin(newPage, pubSite);
64:
65:
66: }
The narrative in what is going on here is:
1. We need to find out if we are dealing with a Publishing Web.
2. Get the Page Layout
3. Create the Page in the pages list.
4. Based on the page name we build that page. (Here is where we can add all the methods to build multiple pages.)
In the switch we call Build Home Page where all the work is done to add the web parts. Prior to adding the web parts we need to add references to the two web part projects in the solution.
using WeatherWebPart.WeatherWebPart;
using CSSharePointCustomCalendar.CustomCalendarWebPart;
We can then reference them in the Build Home Page method.
Let’s look at Build Home Page:
1:
2: private static void BuildHomePage(SPWeb web, PublishingPage pubPage)
3: {
4: // build the pages
5: // Get the web part manager for each page and do the same code as below (copy and paste, change to the web parts for the page)
6: // Part Description
7: SPLimitedWebPartManager mgr = web.GetLimitedWebPartManager(web.Url + "/Pages/Home.aspx", System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
8: WeatherWebPart.WeatherWebPart.WeatherWebPart wwp = new WeatherWebPart.WeatherWebPart.WeatherWebPart() { ChromeType = PartChromeType.None, Title = "Todays Weather", AreaCode = "2504627" };
9: //Dictionary<string, string> wwpDic= new Dictionary<string, string>();
10: //wwpDic.Add("AreaCode", "2504627");
11: //setWebPartProperties(wwp, "WeatherWebPart", wwpDic);
12:
13: // Add the web part to a pagelayout Web Part Zone
14: mgr.AddWebPart(wwp, "g_685594D193AA4BBFABEF2FB0C8A6C1DD", 1);
15:
16: CSSharePointCustomCalendar.CustomCalendarWebPart.CustomCalendarWebPart cwp = new CustomCalendarWebPart() { ChromeType = PartChromeType.None, Title = "Corporate Calendar", listName="CorporateCalendar" };
17:
18: mgr.AddWebPart(cwp, "g_20CBAA1DF45949CDA5D351350462E4C6", 1);
19:
20:
21: pubPage.Update();
22:
23: }
Here is what we are doing:
1. We got a reference to the SharePoint Limited Web Part Manager and linked/referenced Home.aspx
2. Instantiated the a new Weather Web Part and used the Manager to add it to the page in a web part zone identified by ID, thus the need for a Page Layout where the developer knows the ID’s.
3. Instantiated the Calendar Web Part and used the Manager to add it to the page.
4. We the called the Publishing Page update method.
5. Lastly, the Create Publishing Page method checks in the page just created.
Here is a screen shot of the page right after a deploy!
Okay! I know we could make a home page look much better! However, I built this whole Integrated solution in less than a day with the caveat that the Green Master was already built! So what am I saying? Build you web parts, master pages, etc. At the very end of the engagement build the pages. The client will be very happy! Here is the code for this solution Code