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.


Tuesday 22 May 2007

SharePoint deployment options : Features or Content Deployment?

[Update 23/05/07 - clarified emphasis here is on WCM sites and added more detail on conclusion]

Today I want to document some of my thoughts on deployment in MOSS - this article is intended to provide a starting point for analysis of the different ways to deploy SharePoint artifacts between environments, particularly with regards to WCM sites rather than team/collaboration scenarios. At a high level, the options are:

  • create artifacts as features/solutions
  • use SharePoint's Content Deployment framework
  • recreate artifacts manually in each environment

Interestingly, the message from Microsoft and other respected sources was initially that features/solutions was the way to go. This seems to have changed recently with Microsoft's white paper on team-based development in SharePoint. I recommend a thorough reading of this paper, but the summary is:

  • an authoring environment is provided where developers will create artifacts such as lists, site columns, content types, master pages etc. directly (N.B. this is probably the same environment where your client does content authoring using approved master pages/page layouts)
  • artifacts are created directly using the SharePoint UI and SPD rather than using features
  • assemblies should be deployed to this environment (and the final production environment) using SharePoint solutions, to leverage the solution framework's ability to deploy to multiple WFE's in one step
  • Content Deployment is used to get everything (except assemblies and config settings - see above) to the production environment
  • alternatively, the authoring environment can be the production environment if required - use versioning/content approval to control what the end-user site consists of (I recommend having separate environments - I think this is preferable to developing master pages/page layouts in production)

Having gone through the process of creating an entire site with features, I can understand why the guidance would be to avoid using this technique in favour of something simpler. Essentially, I don't think the complexity/overhead of feature development can scale for all MOSS projects, it just takes too much effort. Additionally as I have pointed out earlier, there are issues with updating files which were initially provisioned using one of the original features. However, I also see some limitations with the approach suggested in the whitepaper:

  • the integration environment doesn't make too much sense when you consider that some of the code being developed may require the SharePoint artifacts (site columns, lists etc.) to be present. If they are not created until the authoring environment, this type of code will fail/cannot be tested here.
  • the deployment process effectively means that full integration happens fairly late in the process. The authoring environment is the first environment where all code and artifacts will be present, and this is just one step away from production. In comparison to an architecture which consists of dev/QA/staging (UAT)/production environments, and thus has more than one opportunity to test integration and deployment, this may pose extra risk.
  • one less environment for testing. As in the previous point, some organisations use an internal QA environment for their testing, and then a separate one for client UAT.

An additional environment could resolve some of these issues, but that does mean more content deployment jobs to deal with, and that's not always straightforward.

Despite this, my thinking is that the optimum deployment strategy for a WCM site makes use of both content deployment and solutions/features. The former is used to deploy most SharePoint artifacts (including master pages, layouts etc.), but the latter is used for assets which are mainly based on the filesystem:-

  • assemblies
  • web part definitions (though these go in the database)
  • config settings
  • site definitions (including feature stapling)
  • DelegateControls

(I cover those last 2 items in a forthcoming article btw).

I think this works the best because the feature framework works particularly well for provisioning, but not so well for ongoing site management. This is why there is something of a distinction between WCM sites and team sites. In a team site, the site is provisioned initially with a set of functionality and default content, and then ongoing management is really restricted to development of new bits of functionality (hence features suit this requirement well) and content/documents are added by users. A WCM site often requires very careful lifecycle management of functionality (and content), and I don't think the feature framework caters well for this.

Comments especially welcome on this topic!

Saturday 12 May 2007

Deploying web parts as a feature

This time we're talking about how to deploy web parts as a feature. Now, deploying custom web parts the manual way is a bit of a pain - the following things are required for the web part to be used:-

  • the assembly containing the compiled web part class to be in the GAC (or site bin with appropriate CAS policy)
  • a SafeControls entry in the site web.config to tell SharePoint this control is administrator-approved
  • the .webpart (or .dwp) file which contains the web part definition (configuration) to be uploaded to the site's web part gallery

Assuming the user has appropriate permissions, the web part can then be added to a WebPartZone on a web part page. The first thing to say is that there are 2 ways of automating this process:-

  • use VSeWSS to create a feature to deploy the web part - simply hit F5 to deploy to your local server; this also generates a SharePoint solution package (.wsp) which can be deployed to other environments.
  • create a feature 'manually' by creating the files (e.g. feature.xml, elements file etc.) by hand

Both methods will take care of the 3 steps listed above, so that the files are copied and the SafeControls entry is added. I can't emphasise enough how simple VseWSS makes this process. Additionally, VSeWSS apparently allows simple debugging when F5 is hit, but I had to copy the .pdb file to the hidden folders in the GAC hierarchy to enable this. See my article on how to debug feature receivers for more information.

However, use of VSeWSS typically means there is slightly less control over the deployment options, since the tool writes the files for you and not all of the options are exposed for you to modify (I go into more detail on this in Creating lists with VSeWSS). As an example, VSeWSS will deploy web part assemblies to the GAC (with full trust), but some SharePoint admins prefer assemblies to run from private bin folders instead to isolate any harm they might do. Hence, there are some occasions where you might want to use the second option and create the feature yourself. The remainder of this article illustrates this process, using the example of a web part which should be deployed to a bin folder.

Once the webpart has been developed, we need to create the manifest file, specifying the feature details, assembly, SafeControls entry, and webpart definition file (.webpart):-


Then, we need the feature.xml file which points to the elements file and tells the framework there is another file to process (that being the .webpart file):-



The elements.xml file should look something like:-



Finally, a .webpart file should be generated to define the metadata and default property values of the webpart.




I place this in a folder underneath my feature files alongside the .dll file containing the compiled assembly.

Assuming all the files are in the right place, the solution file (.wsp) can be built using makecab.exe. This solution can now be deployed, thus taking care of the manual steps for webpart deployment. Once this process is familiar (and you have existing files to copy for the next time) this process is quite straightforward.

[UPDATE 22 November 2007 : for bin deployments, the .dll should be at the root of the .wsp file - if it is in a subfolder, it will be deployed to a subfolder of the bin directory which we do not want. See this article's comments for more details.]

Note the DeploymentTarget="WebApplication" instruction in the manifest.xml file. This ensures the assembly is deployed to the application bin folder rather than the GAC. Now, most web parts will require additional CAS policy to obtain the permissions to execute - your assembly will now have the default trust level of WSS_Minimal, so any file io, database or web service access will probably fail. I hope to cover the entries for this in a future article.

So the webpart should now be in the Web Part Gallery and ready to be added to a page.

One thing I also want to discuss is the different ways of adding a webpart to a page. These are:-

  • adding the webpart to a WebPartZone (possible in a feature by use of AllUsersWebPart element)
  • adding the webpart to the HTML markup of a page layout by dragging from SPD

The main thing to note is that if you want to be able to update webpart configuration as part of updating the page layout itself, the webpart should not be in a WebPartZone. If so, the webpart properties are stored in webpart storage, and updating a page layout (either via a feature or manually uploading to the Master Page Gallery) will not change any web part properties. However, note that web part properties can only be edited by a user if the part is in a WebPartZone. This confused me for a while, and is an important facet of the webpart architecture to be aware of.