There are times when you want to have the contents from one page show up in two places. For example, you might have a page with directions to your company’s location in the “About Us” section of your site, but you also might want the same content to show up in the “Products” section of your site so people know where to pick up their product. SharePoint allows you to add a link to your navigation that points to another subsite, but the problem with that approach is that when a user clicks on that link, they’ll be taken to another location, with different left-hand navigation and a different breadcrumb trail. This can be disconcerting for users. However, creating two different pages in two different locations is cumbersome because then a content author who updates one needs to know that the other page exists, and then has to edit both of the pages at the same time.

I solved this problem by created a page layout that has a single field that has a type of the Publishing Rich Link field. An author creates a new page using this page layout. They add the URL of the page they want to get content from to the Link field. When the page is in Display mode, it retrieves the contents of the other page and displays it on the current page, so to an end user it looks like it has the same contents as on the other page. The upside is that when the content author updates the oroginal page, it will be reflected on this immediately.

I provisioned my Link field in CAML like this:

<Field id="{Guid goes here}"
  DisplayName="Source Page URL"
  Group="Custom Columns"/>

I then created my page layout content type that included my new field. (For more information on how to do this, see my post on Creating a Page Layout using Visual Studio 2010.) I created a new Page Layout that included a Literal tag called SourcePageContent. I also put my Source Page URL column inside an Edit Mode Panel, so it’s only visible (and editable) when the page is being authored. Next, I created a custom code-behind page for my page layout. I added this code to my code-behind:

protected override void OnLoad(EventArgs e)
  if (SPContext.Current.FormContext.FormMode == SPControlMode.Display)
    SPListItem currentItem = SPContext.Current.ListItem;
    if (currentItem["SourcePageURL"] != null)
      string urlOfSourcePage = new LinkFieldValue(currentItem["SourcePageURL"].ToString()).NavigateUrl;
      urlOfSourcePage = urlOfSourcePage.Substring(SPContext.Current.Site.ServerRelativeUrl.Length + 1);
      string webUrl = urlOfSourcePage.Substring(0, urlOfSourcePage.IndexOf("/Pages/"));
      SPWeb web = SPContext.Current.Site.OpenWeb(webUrl);
      string[] split = urlOfSourcePage.Split('/');
      string pageFileUrl = split[split.Length - 1];
      SPFile page = web.Lists["Pages"].RootFolder.Files[pageFileUrl];
      SPListItem sourceItem = page.Item;

      if (sourceItem["PublishingPageContent"] != null)
        SourcePageContent.Text = sourceItem["PublishingPageContent"].ToString();

My code has some additional error handling in it, but this is a summary of what it does. Basically, it parses the Source Page URL property, finds the SPWeb object, then looks in the Pages library for a file with the same name. If it finds it, it grabs that file’s SPListItem object and looks for a value in the PublishingPageContent field. (Obviously, you can look for the contents of any field for that list item.)

As a P.S. to this, please keep in mind that you are actually creating two pages in two different locations. Both of these pages will show up in your search results. This can be good or bad depending on what you want, but I just wanted to remind you of that fact. I personally find this approach better than having a “common” list of content that gets pulled into different parts of the site, because on Publishing sites that have the Lockdown mode enabled, users can’t get to lists directly, so you’d have to further tweak your search results to accommodate your common list. This approach doesn’t require that sort of thing, since the files that show up in the search results are pages that users have access to.​​

Hope this helps some of you out there who are trying to accomplish the same thing!