# Friday, May 22, 2009

Curse you PublishingPageLayout!!!!!! Or the discovery of a wonderful "feature" of Sharepoint 2007

*** Please Note that this is done on a "publishing" site, it may be that this issue (I mean 'feature') does not occur on other types of sites. But I doubt it.
 
For those of you unfamiliar with Sharepoint, it combines Master Pages (for overarching look and feel or every page in the site) with Page Templates (which help define how a specific page should be layed out but not the content itself). One way to think of it is that each page in Sharepoint has three levels:

  1. The master page is the highest level and applies to all pages (unless overriden by a page or subsite)
  2. The page template layout determines what 'type' of page (ie web parts page, or article page, or welcome page, or ...)
  3. The actual page content.

Remeber that Master Pages can have parent Master Pages. Page Template Layouts are not considered Master Pages by Sharepoint, but for those of you familiar with the concept of parent/child Master Pages, Page Template Layouts act in the manner similar to a Child Master Page. 

Using Page Template Layouts works wonderfully on Sharepoint unless you have ...

  • more than one server, or ...
  • at least one extension to the server, or ...
  • you move to a new server, or ...
  • you move files from one server to another (via publishing, Sharepoint Designer, manual, etc).

In other words, unless you have a single url to use which never, ever changes, you may be in for trouble.
 
Why? Well it's all relative. Or more specifically it is NOT relative, it is absolute.
 
Basically whenever you create a page it prepends the page layout template section with the URL that you created the page on, turning it into an absolute reference. In other words if you take a look at your page (ex by downloading a copy) you will find that there is a section that reads like this:
 
<mso:CustomDocumentProperties>
... stuff here
<mso:PublishingPageLayout msdt:dt="string">http://theurlthatyouused/_catalogs/masterpage/PageFromDocLayout, Article page with body only</mso:PublishingPageLayout>
... more stuff here
</mso:CustomDocumentProperties>
 
Note that it has prepended the url, whether it be interal - http://myserver:8080 - or external one - http://www.myfriedmind.com.
 
So what does this mean for you? I have good news and bad news.

  • The good news: even if the URL of the page is different (eg calling the page from http://myserver:9090 and not http://myserver:8080 if you extended your site) the page will still show up. Even though the absolute url is different it still pulls it from the database as if it was a relative url. Strange but true.
  • The bad news: You will not be able to edit the page settings from other than the original URL.

If you do, expect this to appear:


 
WHA????????????? Where did that come from? Did someone else modify it? Nope.
 
After choosing Exit Without Saving you might get it to work. Maybe.
 
You might also get this error if you have a webpartpage and decide to edit one of the webparts. Keep clicking on choices until one of them works...
 
Does this remind anyone of being lost in the caverns of Adventures of Zelda? You are in a maze of twisty little passages, all alike...
 
The best is if you try to modify the Page Settings on such a page...

*BOOM*

What has happened is that Sharepoint is looking at the PageTemplateLayout property of the page (which is an absolute reference). If the Server Name and/or Port that you are editing from do not match that exactly then Sharepoint assumes that someone has modified the page between when you started editing and when you try to save it.

Again, one of the ways that Sharepoint tries to determine if your copy is 'dirty' (ie someone has made a change between when you first tried to edit and now) is that it looks at the PageTemplateLayout property. If there is not an exact match it rejects it. If you try to modify the Page Settings it explodes.

  • Scenario #1 - you copy a page from a different URL using Sharepoint Designer - it simply copies the file, including the now INCORRECT URL.
  • Scenario #2 - You are moving your sharepoint to a bigger, faster server (or you are restoring). The new server has a different name...
  • Scenario #3 - You are publishing the pages out to a different front end server but want to be able to edit it from there...
  • Scenario #4 - you are extending a web app to be used on the internet, and you want both internal and external people to be able to edit the same pages, but using different URLs...

etc, etc, etc...
 
What is the solution? Well, there are a couple. One is to use this nifty addition to STSADM - http://stsadm.blogspot.com/2007/08/fix-publishing-pages-page-layout-url.html. Gentleman Gary has done a wonderful job creating a flexible way to repair these beasties. The only caveat - it is an incomplete fix. Basically it still uses an absolute URL, it just replaces the wrong one with the correct one (see his note at the bottom in response to my question). It will fix #1 and #2 above (although if you move it again you will have to rerun it again), but it does nothing for #4. I am not sure about #3 <g>.

Again, note that this does not fix the issue with multiple access, only where a page has been moved. However, if it is simply a matter that you have moved your pages to a different server than this is a pretty rocking solution.
 
I have to deal with #4 after doing #2, so what do I do?

Initially I personally download each file as I uncovered the issue and manually removed the absolute url from the text and replaced it with a relative url and then uploaded the file. I expected a handful to show up, but the number kept increasing. In addition it was a pain for our staff. Sometimes I could spot it after they had made a non-blowing up modification by checking the nvarchar14 in the content database (Select tp_id, nvarchar14 from AllUserData Where nvarchar14 LIKE 'http://%') , but sometimes I would only catch if when they called me to complain.

Btw, if you are thinking that you can just modify the nvarchar14 instead of extracting and modifying the page, it does not work. It will be overwritten once another change is made to put it back to the absolute url. Trust me.

My solution ultimately was to write some code in c# that:

  1. extracted each page
  2. checked it out
  3. inspected the PageTemplateLayout text for an absolute URL
  4. replaced it with a relative URL if that was the case
  5. uploaded the page
  6. checked in the page
  7. published the page
  8. approved the page
I may publish that code in another blog on the off chance anyone is curious about how to do such a thing. This solves Scenario #2 and #4 for me.

Long term? Microsoft???? 

Maybe this is part of the design, or maybe they just missed this. I am just hoping they will fix it. There appears to be absolutely no loss of functionality with a relative reference and even thought there *might* be a case where a page template is housed on another site (and hence a different URL) this is far too serious an issue to sweep under the carpet.
 
I will enter more on another PageTemplate issue in another blog...

Comments are closed.