Issue with customizing default.aspx page through Feature Stapler

 

What is feature stapling and how we will implement it in WSS 3.0?

You can use Feature stapling to effectively replace your use of the ExecuteURL property in a site definition.

Consider the scenario that you want to run some custom code whenever a site is created.

In that scenario, if we are using SharePoint portal server then we can use the ExecuteURL property in an ONET.XML file. Please refer the below MSDN link for getting more information about ExecuteURL property.

https://msdn.microsoft.com/en-us/library/ms977572.aspx

If we are using WSS V3/MOSS, then build a Feature that has an Event Receiver (typically a FeatureActivated event) defined on it and have it catch the Feature activation event. Run your custom code in there. Then, use a Feature Staple to staple your Feature to the GLOBAL site definition (or whatever one you want to run your code for).

In this blog, I am not going to explain more about feature stapling and how we can implement that in WSS 3.0. If you want to more please refer the below MSDN link.

https://msdn.microsoft.com/en-us/library/bb861862.aspx

Scenario:

Now, we can come to the point. Consider you have a requirement that you want to add some webparts or some information to your default.aspx page (which will be the home page of most all OOB SharePoint sites) while creating a new site.

We don’t have any event handlers for site created or web created to capture that event. But, we have a wonderful feature which is nothing but Feature Stapling .

Feature stapling is the one that we need to use in these scenarios.

 

Now we can see the real issue that we are going to face in this particular scenario!

 

The below code is a FeatureActivated which will add an image view webpart to my default.aspx page. I want to execute this code whenever I create a new site. 

Fine! I have created a feature for registering this event handler and I have created a feature stapler to staple my event handler feature to one my custom site template. But, whenever I create a site it was not adding the image viewer webpart to my default.aspx page and there was no any error, what will be the root cause?

public override void FeatureActivated(SPFeatureReceiverProperties properties)

        {

          

            SPWeb oWeb = properties.Feature.Parent as SPWeb;

            oWeb.Title = "I am from feature activation!!";

            SPFile file = oWeb.GetFile("default.aspx");

            if(file.Exists)

            {

                //add webpart

                SPLimitedWebPartManager oWPManager = oWeb.GetLimitedWebPartManager(oWeb.Url + "default.aspx", System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);

                ImageWebPart oImageWP = new ImageWebPart();

                oWPManager.AddWebPart(oImageWP, "Left", 1);

            }

            oWeb.Update();

        }

After thinking some time, I just debugged my Feature Activated event, it was firing correctly and I stepped into the code, line by line, then I found that the condition if(file.Exists)- always returns “false”  clip_image004[4]

Then after researching and searching in net, I was able to understand better about the root cause of the issue by going through the following blogs.

https://blogs.msdn.com/mcsnoiwb/archive/2008/05/28/site-provisioning-order.aspx

https://sharepoint.microsoft.com/blogs/mikeg/Lists/Posts/Post.aspx?ID=1010

 

Those blogs are clearing saying that Features can't depend on lists or files provisioned in onet.xml. Features are provisioned before the actual lists and files which are contained in onet.xml. However, list instances and files defined in onet.xml can take dependencies on list definitions or list instances defined in features.

So, what is happening in our scenario?

Our feature stapler will allow the Feature Activator event to fire and there we are trying to find out the default.aspx page which is not yet provisioned. Default.aspx page will provision only through the onet.xml which is not yet happened. So, how my feature activator event can find out that file from my content DB? 

So that means….if I provision my default.aspx much before the provisioning of onet.xml will work, isn’t it ? then why can’t I try that option? 

Yes I tried that it worked perfectly clip_image007[4] - yehhhhh!

Now let see how I had provisioned my default.aspx.

I have attached custom event handler for Feature Activated event, Feature Stapler files & the feature files for registering the event handler in this post.

Here are the steps to provision the default.aspx file before it is provisioning through onet.xml.

1. Since I have tested with a custom site definition of team site template, I took a copy of default.aspx page from the STS folder and kept it in the Feature activated event registration feature folder..

           clip_image009[7]

2. After that, paste that file in the Feature folder which contains the feature for registering the Feature Activated event.

           clip_image011[9]

You can see that my Feature.xml contains the registration information of the Feature Activated event handler’s assembly and the Elements.xml contains the information for provisioning the default.aspx page. After that you can install this feature and the feature stapler feature and you can create a new site based upon your site template.

In my Feature Activated event I have written the code for adding an image view webpart to the default.aspx whenever we create a new site. You can see the resultant default.aspx screen shot below.

            clip_image013[7]

If you want to know what is provisioning and how we can provision a file please refer the below MSDN article.

https://msdn.microsoft.com/en-us/library/ms441170.aspx

If you want to try it out the sample files that I have attached please follow the below steps:

1. Under the FEATURES folder, create the following subfolders and files (download the AllItems.ZIP – unzip and copy and paste the appropriate files to your Features folder)

· MyFeatureActivatorEvent\

o Default.aspx

o Elements.xml

o Feature.xml

· MyFeatureStapler\

o Elements.xml (Inside here I changed the TemplateName=”STS#0” // for team site templates. If you have any custom team site templates you can try it for that instead of OOB template)

o Feature.xml (if you are making the scope as scope=”Site” then you need activate your stapler feature in your top level site collection, and then whenever you create any sub site you can see that our feature activated event will fire and it will add a webpart to the default.aspx page. If you don’t want to activate it and make this functionality for all whole sites (even for the creation of site collection from the central administration site, then make the scope = “Farm”)

2. GAC the MyFeatureStapler.dll.

3. At a command prompt, type the following commands to install the Features.

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\ stsadm –o installfeature –filename

MyFeatureActivatorEvent\feature.xml

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\ stsadm –o installfeature –filename   

MyFeatureStapler \feature.xml

 

· iisreset

4. Go to any of your site’s site collection feature and there you can see the “My Feature Stapler” feature.

5. Activate it and create a new sub site then you can see that it is provisioning a new default.aspx page with an image view web part and it will change the title of the sub site.

 

All Files.zip