How to: Use Upgrade Code to Activate a Feature with Dependencies

Applies to: SharePoint Foundation 2010

The Feature upgrade infrastructure automatically detects and upgrades Features that have other Features that are dependent upon them, so if you add an <ActivationDependencies> section to your Feature.xml file, you do not need to add any specific upgrade code to support upgrading the Features that are depended upon. However, if the activation dependency is a visible Feature that has not yet been activated, you must write Feature upgrade code to make sure your visible Feature, which other Features depend on, is activated during Feature upgrade. This advanced scenario entails a process to implement custom upgrade code in order to activate a visible Feature that other Features depend on. One example of this process is described in the following advanced Feature upgrade scenario.

Using custom upgrade code to activate a Feature that has Feature dependencies

  1. Add an <ActivationDependency> tag in the Feature.xml file. The <ActivationDependency> element now has a MinimumVersion attribute to provide support for versioned Feature dependencies. In the object model, the SPFeatureDependency class has a corresponding MinimumVersion property that returns the value that is specified in the Feature.xml file. Versioned Feature dependencies are useful when you want to make sure that the required version of the "depended-upon" Feature is installed and activated.

  2. Increase the Feature version number. For more information, see Best Practices for Using Feature Versions.

  3. Add an <UpgradeActions> section in the Feature.xml file, and reference the assembly and type of the Feature receiver. This section specifies the name of an action to perform. In this example, the action "ActivateFeature" is passed to the implementation of the FeatureUpgrading(SPFeatureReceiverProperties, String, IDictionary<String, String>) method that you define subsequently in Step 4.

    <?xml version="1.0" encoding="utf-8"?>
    <Feature 
      Id = "712224F9-6708-4965-A18C-B73CA86AEFCA"
      ReceiverAssembly = "MyFeatureReceiver, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = 3ef91b1292056a22"
      ReceiverClass = "MyFeatureReceiver.MyReceiver"
      Title="My Feature" 
      Description="My feature" 
      Version="2.0.0.0"
      ImageUrl="MyFeature.gif"
      Scope="Site" 
      Hidden="FALSE"
      DefaultResourceFile="core"
      xmlns="https://schemas.microsoft.com/sharepoint/">
      <ElementManifests>
        <ElementManifest Location="Elements.xml" />
        <ElementManifest Location="Elements2.xml" />
      </ElementManifests>
      <ActivationDependencies>
        <ActivationDependency FeatureId="3A4CE811-6FE0-4e97-A6AE-675470282CF2" />
      </ActivationDependencies>
      <UpgradeActions
        ReceiverAssembly="MyFeatureReceiver, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3ef91b1292056a22" 
        ReceiverClass="MyFeatureReceiver.MyReceiver">
        <VersionRange EndVersion="2.0.0.0">
          <CustomUpgradeAction Name="ActivateFeature"/>
          <ApplyElementManifests>
            <ElementManifest Location="Elements2.xml"/>
          </ApplyElementManifests>
        </VersionRange>
      </UpgradeActions>
    </Feature>
    
  4. Implement a Feature receiver that derives from SPFeatureReceiver and that overrides the FeatureUpgrading(SPFeatureReceiverProperties, String, IDictionary<String, String>) method. As shown in the following example, the Feature identifier that you specify in step 3 can be passed to the Add() method to activate visible "depended-upon" Features of the same scope during upgrade.

    public override void FeatureUpgrading(SPFeatureReceiverProperties properties, string upgradeActionName, IDictionary<string, string> parameters)
    {
        if(upgradeActionName != "ActivateFeature")
        return;
        // Get the current Feature that is being upgraded.
        SPFeature thisFeature = properties.Feature;
     
        // Get the parent of the current Feature.
        object featureParent = thisFeature.Parent;
     
        // Get the appropriate Feature collection, based on scope.
        SPFeatureCollection featureCollection = null;
        switch (thisFeature.Definition.Scope)
        {
            case SPFeatureScope.Farm:
                
                featureCollection = ((SPWebService) featureParent).Features;
                break;
     
            case SPFeatureScope.WebApplication:
     
                featureCollection = ((SPWebApplication) featureParent).Features;
                break;
     
            case SPFeatureScope.Site:
     
                featureCollection = ((SPSite) featureParent).Features;
                break;
     
            case SPFeatureScope.Web:
     
                featureCollection = ((SPWeb) featureParent).Features;
                break;
        }
     
        // Get the Feature dependencies.
        SPFeatureDependencyCollection featureDepdencyCollection = thisFeature.Definition.ActivationDependencies;
     
        /* Loop over each dependency and activate it if it has same scope and was not already activated.*/
        foreach (SPFeatureDependency featureDependency in featureDepdencyCollection)
        {
            // Get the depended-upon Feature definition.
            SPFeatureDefinition dependedUponFeatureDefinition = null;
            try
            {
                dependedUponFeatureDefinition = SPFarm.Local.FeatureDefinitions[featureDependency.FeatureId];
            }
            catch { }
     
            // Get the depended-upon Feature.
            SPFeature dependedUponFeature = null;
            try
            {
                dependedUponFeature = featureCollection[featureDependency.FeatureId];
            }
            catch { }
     
            // Get the depended-upon Feature scope.
            if (dependedUponFeatureDefinition != null && dependedUponFeature == null)
            {
                if (dependedUponFeatureDefinition.Scope == thisFeature.Definition.Scope)
                {
                    featureCollection.Add(dependedUponFeatureDefinition.Id);
                }
            }
        }
    }