Showing posts with label SPFeatureDefinition. Show all posts
Showing posts with label SPFeatureDefinition. Show all posts

Tuesday, March 22, 2011

2010 SPWebConfigModifications Applied

I have been noticing a few issues about SPWebConfigModifications and how they are applied.

Service Level SPWebConfigModification Applied

For instance if you have two web applications on your content service one on port 80 and other on port 8080. You can choose to have your web config modifications added to all of web applications by adding them at the SPWebService level.

SPWebService.ContentService.WebConfigModificaitons.Add(myWebConfigModification);
SPWebService.ContentService.Update();
SPWebService.ContentService.ApplyWebConfigModifications();

Advantages:
  • Applied to all web applications at once
  • Applied to new web applications when created
  • Can be used in an auto activated farm SPFeatureDefinition
Disadvantages
  • Will be applied to web applications set up by third party applications that may have special purposes which may damage these applications
  • The actual SPWebModificaitons may reference specific solution based software that may not be deployed globally
Web Application Level SPWebConfigModificaitons

Alternatively it is possible to apply SPWebConfigModificaiton to a specific SPWebApplicaiton.

SPWebApplication myWebApplication;
:
myWebApplication.WebConfigModifications.Add(myWebConfigModification);
myWebApplication.Update();
SPWebService.ContentService.ApplyWebConfigModifications();

Advantages:
  • Scopes to the WebApplication level SPFeatureDefinition
  • Can be added to a WebApplication deployed SPSolution
  • Can be added to a WebApplicaition feature that may be auto activated/deactivated
Disadvantages:
  • Auto activate features always activate on create new web application.  You must make sure all necessary infrastructure pieces are in place to support the new web application as it bootstraps into IIS.
Summary:

In general the create new web application use case is often the most overlooked use case by developers.  SPWebService level SPWebConfigModificaitons will be applied to this use case.  Additionally WebApplication auto activate features will be applied to this use case.  As you program SPWebConfigModificaitons, make sure you do not block the farm administrator from creating new web applications.

Thursday, November 5, 2009

Features are Versioned and Upgradable on SharePoint 2010

One of the big sticking points with SharePoint 2007 was that Microsoft failed to adequately address was how to update between versions of third party SharePoint applications. Microsoft has addressed much of this introduction of feature versioning in 2010.

Starting with SharePoint 2010, the versions of all features activated are stored. Farm and web application features versions are stored in the config database. Site collection (SPSite) and site (SPWeb) features versions are stored in the content database. Features shipped without version numbers default to version 0.0.0.0.

With the in-place upgrade process provided in psconfig.exe, the farm is scanned and the versions of all features activated are compared with the versions of the feature definitions installed. Any active feature that is not up to the current feature definition (SPFeatureDefinition) version has the opportunity to upgrade. How that upgrade occurs depends on a new block of CAML XML in the feature definition under the new UpgradeActions element.

There are several types of UpgradeActions. They include CustomUpgradeAction, ApplyElementManifests, AddContentTypeField, and MapFile. The most flexible of these is CustomUpgradeAction for which you can assign a SPFeatureReceiver. When you do that it will invoke a new method FeatureUpgrading on the SPFeatureReceiver.

Some upgrade code paths must always run. An example of this would be having a base schema for a content type which never changes (because it was released in the past), but always AddContentTypeField regardless of whether deploymenting a new current version or an upgrading to the current version.

At other times, you must use the VersionRange element. This element specifies the affectivity of the upgrade code. An example would be a new module added to older versions.

Over the next few days I will post some examples of using feature upgrade.

Monday, April 20, 2009

Programmatically Activating Features just after Deployment

There are a variety of scenarios where features need to be programmatically activated just after a solution has been deployed.  I have found that even when the SPSolution object says it has been deployed, it really isn’t finished deploying.  Sometimes my SPFeatureDefinitions are either non existents or not installed even when the deployment is “done”.  They eventually do show up. Until they do, feature activation fails when the feature is added to the SPFeatureCollection of the SPFarm, SPWebApplication, SPSite, or SPWeb.  I ended up coding a small bit of code to work around this problem.  This example shows activation of a web application scope feature, but the algorithm can be applied to a feature of any scope.

private void ActivateWebApplicationFeature(Uri webApplicaitonUri, Guid featureId, int timeoutSeconds)
{
    const int sleepTime = 1000;
    for (int i = 0; i < timeoutSeconds; i++)
    {
        try
        {
            SPFeatureDefinition definition = SPFarm.Local.FeatureDefinitions[featureId];
            if (definition.Status == SPObjectStatus.Online)
            {
                break;
            }
            Thread.Sleep(sleepTime);
        }
        catch
        {
            Thread.Sleep(sleepTime);
        }
    }
    SPWebApplication application = SPWebApplication.Lookup(webApplicaitonUri);
    if (application.Features[featureId] == null)
    {
        AddWebApplicationFeature(webApplicaitonUri, featureId);
    }
}

private void AddWebApplicationFeature(string webApplicaitonUri, Guid featureId)
{
    int count = 0;
    while (true)
    {
        try
        {
            SPWebApplication application = SPWebApplication.Lookup(webApplicaitonUri);
            application.Features.Add(featureId);
            application.Update();
            break;
        }
        catch (SPDeletedConcurrencyException)
        {
            // Done. This object is gone so we are finished.
            // Optional logging of condition
            break;
        }
        catch (SPUpdatedConcurrencyException)
        {
            count++;
            if (count > 10)
            {
                throw;
            }
        }
    }
}

The algorithm is to first wait for the feature definition to appear.   When looking up the SPFeatureDefinition in the SPFeatureDefinitionCollection an exception will be thrown until the definition has been added.  The code waits a second between checks.  It continues waiting for the SPFeatureDefinition to install.  Finally it activates the feature if the feature needs activation (in certain upgrade scenarios the feature may already be active).  You will notice that the second method uses my technique to control SPDeletedConcurrencyException and SPUpdatedConcurrencyException

Thursday, April 2, 2009

Uniquely Name Features

For SharePoint Features deployed into the 12 hive at the root of the feature directory it is necessary to remember that the name of your feature must be unique. The 12 hive feature (12\Templates\Features) directory is a global namespace and your feature directory should not trample another third party feature. I recently had to explain this to a developer who was provisioning “SearchWebPart” a feature with a very generic name.

My recommendation is to use the following naming convention for your feature directory: CompanyApplicaitonFeaturename. By doing this you will avoid colliding with other features deployed by other solutions running in the SharePoint farm.

Monday, March 30, 2009

Activate-Once Hidden Farm Features

To create a dependent farm feature that is hidden and will activate only once, use a resource-hidden feature.  I explained Friday that hidden features automatically deactivate when the last feature dependent upon the hidden feature deactivates and that resource-hidden features do not.  So using a resource-hidden feature the feature does not deactivate.

The problem is that resource-hidden features do not automatically activate in the activation tree.  The solution for farm level features is to set the attribute ActivateOnDefault=”true” in the feature element API.  This will activate your farm level feature on deployment. Here is the feature.xml for the SPFeatureDefinition:

<?xml version="1.0" encoding="utf-8"?>
<Feature xmlns="http://schemas.microsoft.com/sharepoint/"
         Id="C595997F-F3DD-4677-82CF-02AF9FB73451"
         Title="$Resources:Resource_hidden_feature_DO_NOT_LOCALIZE"
         Description="$Resources:Resource_hidden_feature_DO_NOT_LOCALIZE"
         RequireResources="true"
         Hidden="false"
         Scope="Farm"
         ActivateOnDefault="true"
         ReceiverAssembly="My.Receiver.Assembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8d63fadacc3f6a0e"
         ReceiverClass="My.Receiver.RunOnceFarmFeatureReceiver">
</Feature>

In this example the code in the SPFeatureReceiver is run only once at initial SPSolution.Deploy.  The feature is resource-hidden so users cannot see it and will not deactivate it from the Central Administration UI.  The feature also will not be deactivated by any features which depend on this feature.   The feature will only be deactivated prior to uninstall.

Thursday, March 26, 2009

Resource-Hidden Features can have ActivationDependencies

What is a resource-hidden feature?  It is a feature that is hidden from the user using a loophole in the SPFeatureDefinition API that is intended to show locale specific features.

Basically the feature element API says that the attribute RequireResources=”true” will prevent a feature from appearing in the GUI feature list if a resource file for the locale cannot be found.  A resource-hidden feature exploits this by providing no resources for any locales. Here is what the feature.xml looks like:

<?xml version="1.0" encoding="utf-8"?>
<Feature xmlns="http://schemas.microsoft.com/sharepoint/"
         Id="C595997F-F3DD-4677-82CF-02AF9FB73451"
         Title="$Resources:Resource_hidden_feature_DO_NOT_LOCALIZE"
         Description="$Resources:Resource_hidden_feature_DO_NOT_LOCALIZE"
         RequireResources="true"
         Hidden="false"
         Scope="Site">
  <ActivationDependencies>
    <ActivationDependency FeatureId="0D7EE02B-F92F-4ed2-97F7-349AEC1E0517" />
    <ActivationDependency FeatureId="5730DE72-D669-4fc7-9EA1-BC50826EF575" />
    <ActivationDependency FeatureId="C3BAA93D-B3DE-424c-850A-E19253068473" />
  </ActivationDependencies>
</Feature>

You might ask why would you use a resource-hidden feature instead of a regular hidden feature with the attribute Hidden=”true”?  Simply because the two have different behaviors:

·         Activation – Hidden features auto-activate in the feature dependency chain. Resource-hidden features do not.

·         Deactivation – Hidden features which are dependent features, deactivate when the last feature depending upon them deactivates. Resource-hidden features do not.

·         Dependency  Tree – Hidden features cannot have any ActivationDependencies. Resource-hidden features can.

Remember resource-hidden features cannot be seen in the UI and do not auto-activate so they must be programmatically activated by adding them to a SPFeatureCollection.