<Update>Check out this later post zevenseas Feature Blocker which basically is an update of this post. Or go to CodePlex and download the solution immediatly ;) </Update>
If you want to prevent users from activating certain out-of-the-box features like the Publishing feature on a non-publishing site there isn’t really much you can do about it. When I was solving this problem the first thing that sprung into mind was to attach an event handler on the feature activating method but unfortunately there is no event handler available to do this (MS if you read this.. this is on my O14 wish list as well from now on :)
<TR><TD class="ms-vb2" style="font-weight: bold;"><H3 class="ms-standardheader">Office SharePoint Server Publishing Infrastructure</H3></TD></TR>
<TR><TD class="ms-vb2">Provides centralized libraries, content types, master pages and page layouts and enables page scheduling and other publishing functionality for a site collection.</TD></TR>
<TD class="ms-alternating" style="padding-top: 4px; padding-bottom: 4px;">
<input type="button" name="ctl00$PlaceHolderMain$featact$rptrFeatureList$ctl33$btnActivate" value="Activate"
id="ctl00_PlaceHolderMain_featact_rptrFeatureList_ctl33_btnActivate" class="ms-ButtonHeightWidth" />
var siteButton = document.getElementById('f6924d36-2fa8-4f0b-b16d-06b7250180fa').childNodes;
siteButton.disabled = true;
So I had a little discussion with some of my SharePoint friends namely Daniel and Waldek (who now is MVP!) and got two suggestions:
- Write a HTTPModule
- Write a ControlAdapter
- Next it’s time to let SharePoint know that you have created an adapter by creating a .browser file that sits in the App_Browsers folder. First you specify which control you are trying to override and secondly you specify which control must be used for the overriding. It looks something like this::
<adapter controlType="Microsoft.SharePoint.WebControls.FeatureActivator, Microsoft.SharePoint.ApplicationPages,
Version=126.96.36.199, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
- You may have never guessed but this stuff actually works! And now the tricky part.. making this deployable! ;) I’ve never had to put anything in the folder of a WebApplication folder so I was checking all the properties and methods of the WebApplication class and then I found the SPIisSettings class! Time for a new paragraph..
This class gives you access to the WebApplication folder of the specified UrlZone (Default/Intranet/Extranet/etc). If you take a look at the following code (that could do a little more polishing, I know..) that is implemented in a web application scoped feature receiver I get a reference to the App_Browsers folder to store the .browser file in. By using the Properties element in the Feature.xml I also get a reference to the .browser file that resides in the feature folder. So by combining the two paths I can use a StreamReader and a StreamWriter to copy the file across.
SPWebApplication webApplication = (SPWebApplication) properties.Feature.Parent;
SPIisSettings iisSettings = webApplication.GetIisSettingsWithFallback(SPUrlZone.Default);
//Setting the destination folder
string destinationPath = iisSettings.Path + @"\App_Browsers\preventpublishing.browser";
FileInfo fi = new FileInfo(destinationPath);
//Getting the folder where the custom .browser file is
string filePath = properties.Feature.Properties["Path"].Value;
using (StreamReader sr = new StreamReader(filePath))
using (StreamWriter sw = fi.CreateText())
// Read and display lines from the file until the end of
// the file is reached.
while ((line = sr.ReadLine()) != null)
And that’s pretty much it! :) After all this.. this is how the end-user sees the page:
Some very useful references that helped me :