Wednesday, 30 May 2007

Feature stapling

One aspect of features I wanted to cover quickly is the relationship SharePoint Features have with site definitions. Site definitions are created by a developer and subsequently used by site owners to create new sites. Much of this facility is also available by the 'Save site as template' functionality, though there are some minor differences. Additionally the 'Save site as template' functionality is removed on SharePoint publishing sites (or at least the link in Site Settings is via a HideCustomAction feature element), due I think, to some site information/functionality which SharePoint cannot properly save into a .stp file. So developers often create site definitions as part of their customization, and it's a process well-documented in the WSS SDK.

If you have created a site definition, there are several ways of using features with it. These are:-

  1. Create a site from the definition and subsequently deploy your features to the site.
  2. Include the features in the site definition (onet.xml) before using it to create sites.
  3. Use feature stapling to associate your features to the site definition.

Since the first option doesn't really associate the Features to the site definition, we'll focus on options 2 and 3.

2. Include features in site definition

This option should be used if the site definition has not yet been deployed, and no sites have yet been created from it. The section of the onet.xml file where features are associated with the site definition contains may look something like:

<Configuration ID="0" Name="BLANKINTERNET">

    <SiteFeatures>

        <Feature ID="C85E5759-F323-4EFB-B548-443D2216EFB5" />

        <Feature ID="A392DA98-270B-4e85-9769-04C0FDE267AA" />

        <Feature ID="7C637B23-06C4-472d-9A9A-7C175762C5C4" />

    </SiteFeatures>

    <WebFeatures>

        <Feature ID="00BFEA71-DE22-43B2-A848-C05709900100" />

        <Feature ID="00BFEA71-E717-4E80-AA17-D0C71B360101" />

    </WebFeatures>

    <Modules>

        <Module Name="Home" />

    </Modules>

</Configuration>


The ID value is, of course, the feature GUID. The SiteFeatures element contains features which should be activated when the site definition is used to create a site collection, and the WebFeatures element contains features for when the definition is used to create a standard web within a site collection.

3. Use feature-stapling to associate your features to the site definition

This option should be used when the site definition is already in use (and sites have been created). This is because there are risks in modifying a site definition once it has been deployed, since the site definition files on the filesystem are used for pages which are ghosted (not modified).

To use feature-stapling, you first need the feature(s) you wish to link to the site definition - these should be created in the normal way. The, you should create a 2nd feature which does the actual stapling. Sample values for the various files are shown below:

The manifest.xml file if you are wrapping your feature in a solution:

<?xml version="1.0" encoding="utf-8"?>

<Solution xmlns="http://schemas.microsoft.com/sharepoint/" SolutionId="26E1A1D9-7BB2-4e76-888E-B20184B16E3B">

  <FeatureManifests>

    <FeatureManifest Location="COB.Demos.FeatureStapling\feature.xml" />

  </FeatureManifests>

</Solution>

The feature.xml file which defines the feature 'header' information:

<?xml version="1.0" encoding="utf-8" ?>

<Feature Id="4AF9999A-0517-4224-9ED3-D2F9F87D92E2"

        Title="COB.Demos.FeatureStapling"

        Description="Staples a set of features to custom site definitions. The features/site definitions are defined in stapling.xml."

        Version="1.0.0.0"

        Scope="Farm"

        Hidden="FALSE"

        xmlns="http://schemas.microsoft.com/sharepoint/">

  <ElementManifests>

    <ElementManifest Location="stapling.xml" />

</ElementManifests>

</Feature>


And finally, the core feature definition in the stapling.xml file:

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

  <FeatureSiteTemplateAssociation Id="F6924D36-2FA8-4f0b-B16D-06B7250180FA" TemplateName="MySiteDefName#0" />

  <FeatureSiteTemplateAssociation Id="94C94CA6-B32F-4da9-A9E3-1F3D343D7ECB" TemplateName="MySiteDefName#0" />

  <FeatureSiteTemplateAssociation Id="02464C6A-9D07-4F30-BA04-E9035CF54392" TemplateName="MySiteDefName#0" />

</Elements>



The FeatureSiteTemplateAssociation element maps feature GUIDs to site defintions - note that the format of the TemplateName attribute value is <SiteDefName>#<ConfigurationID>. This obviously allows a degree of flexibility and allows you to do fairly complex things with different configurations of site definitions.

The final thing to note is that feature-stapling won't affect any sites which have already been created from a site definition, only subsequent sites. The only way to do this is to activate your features individually on the site, though obviously an STSADM script can help you activate multiple features against multiple sites.


40 comments:

Anonymous said...

Hi Chris

Thanks for nice article.

Can I add site-collection scoped feature to the web using feature stapling?

So that when I create a new site my feature gets activated.

Best regards

Amit

Chris O'Brien said...

Amit,

Yes, you can staple a feature which is scoped at site collection. However, bear in mind that the feature will then be at the level of site collection rather than web. This means that when the site definition is used to create a top level site (i.e. site collection), the feature will be automatically activated.

Hope this helps,

Chris.

Stijn said...

Hi Chris,

Thanks for the good read.

I have an additional question about the feature stapling. When i use the following statement,

FeatureSiteTemplateAssociation Id="94C94CA6-B32F-4da9-A9E3-1F3D343D7ECB" TemplateName="GLOBAL"

It should affect all site templates if i'm right. Does it also apply to site templates that will be created in the future?

Thanks in advance.

Stijn

Chris O'Brien said...

Stijn,

Yes, you are correct in that all sites will have the Feature if it is stapled to the GLOBAL template. However, note that Feature-stapling only affects sites which are subsequently created, not sites which exist already.

To amend sites already in existence, you need to deploy the Feature to them separately using STSADM -o installfeature/STSADM -o activatefeature.

HTH,

Chris.

Anonymous said...

Hi Chris,

Thanks for the article, It really help me a lot.

Now I have a question regarding custom site template,

In the article you are talkng about the stapling of feature to a site definition, but is there a way that I can stapling the feature to a custom site template in the site template gallery?

I tried when create a new site with a custom site template instead of a site definition, the feature is still in the new site, but it is not activted by default, you have to manually activited the feature, is there a way you can make the feature activited by default?

John

Chris O'Brien said...

Hi John,

That's an interesting question. In actual fact this highlights one of the differences between site definitions and site templates. A site template is simply the customizations or changes (i.e. the 'delta') which have been applied to the site since it was created from the base site definition. As a result, a site template will only work if the base site definition is present on that SharePoint web server.

I think the reason you're seeing the Feature present but not activated by default, is because in the base site definition which was used, the Feature was also present but not activated by default. In other words, this behaviour is attached to the site definition, not the site template.

So I think you'd need to work with a custom site definition to achieve what you want.

HTH,

Chris.

Anonymous said...

It seems the statpled feature gets activated before the site provisioning is finished, on activation of feature code we are trying to access the list but we get an error message, list not found.
Is there anyway to get the feature activated after the site provisioning is finished

Mike
Mike

Chris O'Brien said...

Hi Mike,

Unfortunately I don't think there is. If I remember correctly, sites/webs are available but not anything 'smaller' such as a list or item. Obviously this is pretty inconvenient.

A couple of options could be:

- create an SPTimer job in the Feature receiver, this would then perform the processing afterwards
- come at it from a different angle by deriving from SPWebProvisioningProvider to have control over the code which executes in the provisioning process. I've never done this, but you might be able to call the base method then do your work immediately afterwards.

Be interested to hear how you get on if you try either of those approaches. Best of luck..

Chris.

MntlChaos said...

The best approach I've handled in this situation (stapled feature depends on list in site definition) is to put the list into the feature.

Chris O'Brien said...

Ah interesting, I can see how that would probably work. That's good stuff, thanks for the comment.

Chris.

Sanjay said...

Hi Chris,

If I staple my custom feature with Team site defination. Does it mean whenever I create a site using team site template, my custom feature will get activated automatically?

Thanks,
Sanjay

Chris O'Brien said...

Hi Sanjay,

Yes that's exactly right. Since it isn't supported to modify out-of-the-box site definitions, this provides us a way of adding custom functionality to the standard definitions.

HTH,

Chris.

Bhakthi said...

Hi Chris,

Thank you for the great article.

According to the post, new Features will be deployed only to the newly created sites. is there any way that I can deploy the new Features to existing sites without using STSADM? Can I do this in the code on 'FeatureActivated' event?

Thank you,
Bhakthi

Chris O'Brien said...

Hi Bhakthi,

You could make changes to all the sites in your hierarchy from within one Feature activation, but this doesn't really fit the model too well. When a Feature is activated against a site the idea is that it will only modify that site.

My recommendation would be to keep to that model if you can - anything else could get confusing, not least to other developers/admins in your SharePoint environment.

HTH,

Chris.

Saurabh said...

Hi Chris....

I am trying to do this thing.....
I want to add Sites List in my Team Site...is it possible to add SITES lists in a Team Site....??

Chris O'Brien said...

@saurabh,

Not sure if you mean to add a list of sites to a single team site or to the team site definition (so that all subsequently-created team sites get the list), but either way this would be possible.

- single team site: add/edit a web part page and add appropriate web part (e.g. Table of Contents web part, Summary Link web part)
- team site definition: staple a feature which adds appropriate web part to a new web part page using 'AllUsersWebPart' tag

HTH,

Chris.

Dennis Bottjer said...

Chris,

Just wondering how often you create custom site definitions? I've generally prefered using an out of the box site definition then adding or removing artifacts (Lists, Web Parts, etc.) to the site via the Features with the object model. Custom Site defs add tons of XML to maintain and debug and personally I prefer C# to angle brackets. What are your thoughts?

Thanks,
Dennis

Chris O'Brien said...

Hi Dennis,

To be honest my recent focus has been on WCM sites, where the whole emphasis is away from site definitions and the collaboration pieces anyway. However, I think the idea of adding Features to a standard site definition can often work better, but I guess it often comes down to if many sites are being created from a template or all the customizations are oriented around one site.

I can see the attraction of working with Features through code, but if everything is still based on the Features framework, do you really get away from the XML?

Cheers,

Chris.

Seno said...

Hi Chris,

I have a normal feature scoped at Site level that creates a doc lib without using an FeatureEventReceiver (just xml).

This feature is working normally when activated manually but when I use a Stapler-feature to link this first feature to the Global#0 definition it doesn´t work. My stapler-feature is scoped at Farm level and new site collections doens´t have the new doc lib.

Any suggestion?

Cheers

Fábio

mvmsastry said...

Chris,
Do you know how we can destaple the feature after we stapled out.

I have observed that when we deactivate the feature(that staples another feature) the destapling is not happenning.

Thanks,
Venu

Yesh said...

Hi Chris,

Thanks for the Nice post. I have a question regarding Activation> I have a feature at Farm level and one at web level having Item Events which is stapled to "GLOBAL". However I am seeing that whenever I create a site, though my feature is activated,it is not triggering the events in the feature. It would be very helpful if you can guide me regarding this.

Chris O'Brien said...

@Seno,

Hmm, sorry don't have too many ideas there, don't see anything too wrong with what you're doing. You might want to try scoping the feature at site collection though to see if that could be the problem.

HTH,

Chris.

Chris O'Brien said...

@mvmastry,

Do you mean that new sites which are created from the definition after the Feature has been deactivated continue to have the stapled feature? If so that's a good question and I'm afraid I don't know the answer! It could be that you need to run some code in the Feature deactivation to do this.

However, if you're expecting the Feature to be deactivated from sites which have already been created when the stapler was activated, I wouldn't expect this to happen - you'd need to go round each site and deactivate the stapled Feature.

HTH,

Chris.

Chris O'Brien said...

@Yesh,

I wonder if your issue is connected to the permitted scopes for the various Feature elements. Suggest checking the Elements by scope matrix to ensure you're not doing anything which doesn't make sense.

HTH,

Chris.

Anonymous said...

Hi Chris,

Thanks for your reply. I will look at this and will keep you inform.

-Yesh

Paul Mc said...

Great atricle. I have a question though having come across some difficulties.

I have created my staple at farm level and have installed a number of features in central admin that have been deployed to existing sites.

I create a new site with a staple to deploy a list of features which are scoped at Site collection level.

The features get activated successfully but the deployment isn't happening it would seem.

This is a facet of SharePoint I don't understand but because the features have been installed on other sites they appear in the list of site collection features for every site.

When the new site is created they are available to be activated. However because they have not been officially deployed to the new site the content types are installed because the feature has the correct files in the 12 hive, but the web part dll and the safe control tag are only performed when deployed which the staple doesn't seem the be doing.

Chris O'Brien said...

Paul Mc,

Sorry for the delay in getting to your comment. I'm not sure I quite follow what your issue is - do you mean that the Features are being activated but their artifacts aren't being provisioned?

If so, suggest checking your artifacts against the Feature elements by scope table to make sure you're using the right scope for the different things.

HTH,

Chris.

dejawoo said...

hi Chris,

I guess answer to this question has been already given,just a little bit obscure yet, would like to pose again. Logically since I have a feature which is site collection scoped, expectation would be it will be automatically applied(activated) at the time of new site collection is created. seems I m getting it even while I m creating a new site(web). is that normal behavior. can you pls. elaborate a bit. thanks.

Anonymous said...

Hi,

I have been having an issue with stapling and site templates (.stp)

If you have a feature with event receivers at the list level (itemAdded etc) enabled on your site, then, save that site as a template using (save this site as a template) and then create a new site from that template, the event receivers will be registered twice with the lists... They will register with a different sequence number but the same event name.

Something like:

CustomItemAdded : Sequence: 1000
CustomItemAdded : Sequence: 1001

This is really annoying since it makes the event receivers fire twice and the code runs twice which can lead to error in some occasions.

Is this a known issue?

madhusudhan said...

Hi Chris,
I have created about 10 sites out of a custom created site definitions using visual studio extensions.
Then after deploying to production changes came to the existing sites.
I made changes to the existing site definition in the visual studio and generated a wsp file and then deployed it in to production.And this worked for old sites also.

Then again when next time changes have come so again I changed the sitedefintion and deployed them. This time all the existing sites are broken and they stopped working.

Upoun investigating further I came to know some times only the sites are breaking.

My question is which is a puzzle to me is how to make changes to the site defintion without breaking the older sites? Is it Possible ?

Anonymous said...

I want to update some files in the Blog Site (post.aspx, schema.xml) without creating an other sote definition.
Can I use the stapling feature to overwrite the default files and when I deactivate the Blog Site the files should have the original status.
Is that possible and how?

Thanks in advanced.

Alex

Chris O'Brien said...

@dejawoo,

It's been a while since I've used Feature stapling, but I'm not sure I would expect the behaviour you're seeing. Although your Feature is scoped for a site collection, are you sure the elements within the Feature can belong at this scope?

HTH,

Chris.

Chris O'Brien said...

@Anonymous,

Interesting finding - it does sound like a bug, I'd raise a call and see if you get any joy from PSS.

Be interested to hear the result if you do.

Chris.

Chris O'Brien said...

@madhusudhan,

Briefly, it's not supported to make changes to a site definition which is already in use (i.e. sites have already been created from it).

The Feature stapling approach can help you out in this scenario though - this allows you to add Features (and hence, execute code) without touching the original site definition files.

If you really do need to modify the site definition, you can create a subsequent 'version' by copying/renaming the original site definition, making the updates, and then hiding the original version by deleting the *webtemp.xml. This means new sites can only be created from the new version and existing sites continue to function unaffected. If you want those existing sites to also reflect the changes, you'll need to do some work to apply them, typically this will involve using the API.

HTH,

Chris.

Chris O'Brien said...

@Anonymous,

I wouldn't use this approach - it's not supported to modify out-of-the-box site definition files, so I'd suggest creating your own definition based on a copy of the standard one.

HTH,

Chris.

Anonymous said...

I can see that it should be nice to use feature stapling when I use builtin site definition (from MOSS or WSS) but when i alread have a custom site definition why would i use feature stapling instead of modifying the site definition? but i have a much more important question here... if i have files inculded in a custom site definition (i mean ASPX file or image or whatever else) that i added to site definition after site creation... is there a way to rexecute the modules so it add new files to existings sites or i will be forced to use a new feature and then have file in directory of my feature been used instead of the one in my site definition??

Chris O'Brien said...

@Anonymous,

Interesting points, but for me you've actually answered your own question. The very reason to develop your functionality in Features which are then stapled to your 'skeleton' site definition is because you have more flexibility - as an example, if you develop in this way you can easily deploy your new functionality to existing sites (by activating the Features against these sites) and for new sites (by stapling the Features to the site definition). As you've found, dealing with existing sites isn't catered for when you add all the functionality directly to the site definition. Also keep in mind that it isn't supported to change the actual site definition files once sites have been created. Andrew Connell also talks about this in his post You don't need to create site definitions, and a good point he raises is that you also have the capability of removing functionality by deactivating Features if you want - another thing not possible with everything in the site definition.

HTH,

Chris.

Anonymous said...

Hi Chris,

I have a feature stapler that works just properly in my development environment. When I move it to test, the "Stapler" stops working. I am using solution deployment to deploy both my feature and my feature stapler. I am stapling to the STS#0 and GLOBAL#0 site defs.

Any insight would be appreciated.

-Anon

Chris O'Brien said...

@Anon,

Sorry I don't have any specific ideas on that one..

Good luck,

Chris.

Cameron said...

I struggle for half a day before discovering that the feature that is being stapled has to be web scope

I hope this comment helps someone else....