Meta: Attributes in Page Layouts Provisioned by Features are Unghosted (Customized)

One of my clients was having an issue where solution upgrade or redeployment didn’t change certain page layouts. I checked the CustomizedPageStatus property of the affected layouts and it said they are customized. However, they had not actually been customized.

I activated the problem feature in another environment. Much to my surprise, the particular layouts indicated that they were customized immediately based on the provisioning for the module!

I didn’t see any difference between the couple of layouts that exhibited this behavior and the others in the same module that were appropriately uncustomized post provisioning. Also, I observed that on a stock publishing portal site with no customizations the same is true of VariationRootPageLayout.aspx.

I figured I couldn’t be the only one to have seen this behavior, so I asked the Internet and fellow MVP Rodrigo Pinto gave me the answer which I am blogging here in hopes that you’ll have better luck finding the answer with the search engine of your choice than I did!

The affected page layouts all contained meta: attributes from SharePoint Designer as shown in the following example.

 

<%@ Page					
language="C#"   Inherits="Microsoft.SharePoint.Publishing…"
meta:progid="SharePoint.WebPartPage.Document" meta:webpartpageexpansion="full" %>

The presence of these causes SharePoint to ‘unghost’ or customize the page upon the initial provisioning. The affect is exactly the same as if the page was manually modified or uploaded into the library – subsequent upgrades do not affect the version in the site. I removed these from each of the affected layouts and checked in the changes. Once we upgraded the solution were able to run a script to re-ghost (uncustomize) the affected layouts. The script used Gary Lapointe’s excellent extensions: http://blog.falchionconsulting.com/index.php/2007/09/re-ghosting-pages/

–Doug

Author: Doug Ware

Monkey Patching and SharePoint / Office 365

This post is a prelude for the one to follow in which I will show an application of this technique that overrides the workspace sizing routine in SharePoint 2010.

JavaScript is a wonderful language. It is easily accessible to anyone who understands C style syntax. This includes C# developers. However JavaScript is a dynamic language. In my experience most C# developers write poor JavaScript in a style that is appropriate to C#. However, getting the most out of SharePoint requires a good understanding of JavaScript and I am not talking about using jQuery or the Client Object Model. I am talking about fundamentals!

This is especially important if you are working in a sandbox environment like Office 365. It is very difficult (and often impossible) to fully achieve your UI goals given the restrictions of the sandbox architecture on the server side. However, with a good command of client side technologies, especially JavaScript, you can overcome many of these limitations.

The problem is that most of the really interesting components in SharePoint’s JavaScript libraries are undocumented. Furthermore, the chances are good that if you make heavy use of what I am about to show you, you will be disappointed when you have to fix your work when the next version of SharePoint drops and these undocumented libraries change. So, consider that fair warning – this is a powerful technique, but one with serious risks over time!

As Wikipedia tells us: ‘A monkey patch is a way to extend or modify the run-time code of dynamic languages without altering the original source code. This process has also been described as "duck punching".’

In JavaScript a function is a type and you can do things to functions that C# just doesn’t allow. You can assign them to variables, pass them as arguments, and even change their values.

For example (see it here on jsFiddle):

function sayHi() {
alert('Hi!');
}


function doFunction(func) {
func();
}


doFunction(sayHi);

 

 

This may be one of the longest Hello World style examples you can write! In it the function sayHi is invoked via the doFunction function by passing sayHi as an argument.

Now, imagine that sayHi is actually part of one of SharePoint 2010’s JavaScript libraries and you don’t like how it works. In a farm deployment scenario you could (but never, ever should) just open the file in the SharePoint root and change it. This is not an option in sandbox mode because you have no access to the actual script file. This is where monkey patching comes in.

Consider this example (see it here on jsFiddle):

function sayHi() {
alert('Hi!');
}


function doFunction(func) {
func();
}


var oldSayHi = sayHi;
sayHi = function() {
alert('What is the opposite of bye?');
oldSayHi();
}


doFunction(sayHi);

 

In this version the code copies the pointer to the original sayHi function into a new variable and then changes the value of the variable sayHi to a new function that shows a different alert before calling the original version and you get two alerts. This, in a nutshell, is what monkey patching is all about. With it you can replace an existing function completely or do custom pre/post processing as shown in the example above.

To get a feel for what you might do with this technique, add the following script via a Content Editor Web Part to the home page of a stock team site and then add a new Shared Document by clicking the link.

if (typeof NewItem2 != 'undefined') {
    var oNI2 NewItem2;
    NewItem2 this.NewItem2;
}


NewItem2 function(eventurl) {
    alert('NewItem2 called');
    oNI2(eventurl);
};

 

You should see something similar to the following.

For those of you who inherit nightmares because of misuse of this technique; I’m sorry!

Happy coding!
–Doug

Author: Doug Ware