One of the nice features of SharePoint 2010 is the possibility you actually have to version your features and update your features in a more sensible way than the previous version did. In SharePoint 2007 the feature had a version property, which basically allowed developers to keep track of the versions themselves – SharePoint did in other words never use the property for anything.
Times have changed – in SharePoint 2010 the application Lifecycle Management actually allows you to upgrade your features which in the simplest form lets you change the name of previous uploaded files, add an additional element-file or the thing I have seen cause the most WAUW-effect during the Ignite-trainings I have held in Denmark – adding fields to an already deployed content type in your farm. In this walk-through our goal is to accomplish the last scenario – so let’s start up. I have a newly created team-site with no customizations accomplished on the url http://intranet
Creating the basic content type feature
So let’s start up by creating a basic feature with a content type with a single note-field – just to have something to play around with
- Open Visual Studio 2010 and create a new Empty SharePoint Project – my project is named TheUpgradeableCT – and the name will be important later, so if you chose another name, some of the walkthrough won’t be completely copy/paste. Deploy it as a farm solution against http://intranet or whatever site collection you wish as a debug-site – again – I will use the url later
- Right-click the project and add a Content Type Item to the project – name it The Upgradeable Content Type and chose Document as the base content type when the wizard appear and click Finish.
- Paste the following into the elements-file created in your content type node – this will create a basic document content type
<?xml version=“1.0” encoding=“utf-8“?>
<Elements xmlns=http://schemas.microsoft.com/sharepoint/>
<!– Parent ContentType: Document (0×0101) –>
<ContentType ID=“0x0101009214903b71c048a0ba7a7ec3dff0d9dd“
Name=“TheUpgradeableCT“
Group=“A feature upgrade attempt“
Description=“The upgradeable content type“
Version=“0“>
<FieldRefs>
<FieldRef ID=“{67BC24C5-C864-4CE5-9855-B515EEF54773}“/>
</FieldRefs>
</ContentType><Field ID=“{67BC24C5-C864-4CE5-9855-B515EEF54773}“
Name=“Note1“
StaticName=“Note1“
DisplayName=“Note on version 1“
Type=“Note“
Group=“A feature upgrade attempt“/>
</Elements>
-
Change the version number of your feature by double clicking the feature node and change the feature version to 1.0.0.0 in the Properties window of your feature

- Deploy your solution and check that your content type is deployed successfully – and create a document library and attach the content type to it in the UI.
Make the extra field for the Content Type for version 2.0.0.0
For version 2.0.0.0 we will add an additional custom field for our content type and make the initial configuration of our feature ready for upgrading to the new verison, so let’s hit it by adding a new Field Item to our Sharepoint project and package the project to make it ready for the upgrade-celebration:
- Right-click the project-node of your Visual Studio Project and add an Empty Element called Version2Fields. It contains an element.xml, in which you put the following field, which will be the additional field of our feature in version 2.0.0.0:
<?xml version=“1.0” encoding=“utf-8“?>
<Elements xmlns=http://schemas.microsoft.com/sharepoint/>
<Field ID=“{67BC24C5-C864-4CE5-9855-B515EEF54774}“
Name=“Note2“
StaticName=“Note2“
DisplayName=“Note on version 2“
Type=“Note“
Group=“A feature upgrade attempt“/>
</Elements>
- Expand your feature node untill the template.xml appears…open it. This is basically your feature without all the properties in it. Place your cursor between the open and close feature tag and add an UpgradeActions element with a corresponding closing element.
- In the UpgradeActions place a VersionRange to tell the versions you are upgrading from and to. Give it the properties BeginVersion=”1.0.0.0″ and EndVersion=”2.0.0.0″.
- Between the versionrange you can specify what will happen when we are upgrading from version 1 to 2. In our case we will add an additional elementfile, so insert a ApplyElementManifests and put a ElementManifest inside here with a location of your additiona element file
- Furthermore we need to add this field to the content type we just made – so add an AddFieldToContentType and give it the id of the content type and the field and specify whether to pushdown the field to all content types inheriting from the specified content type. Your Feature file should look something like this
<?xml version=“1.0” encoding=“utf-8“ ?>
<Feature xmlns=http://schemas.microsoft.com/sharepoint/>
<UpgradeActions>
<VersionRange BeginVersion=“1.0.0.0” EndVersion=“2.0.0.0“>
<ApplyElementManifests>
<ElementManifest Location=“Version2Field/Elements.xml“/>
</ApplyElementManifests>
<AddContentTypeField
ContentTypeId=“0x0101009214903b71c048a0ba7a7ec3dff0d9dd“
FieldId=“{67BC24C5-C864-4CE5-9855-B515EEF54774}“
PushDown=“TRUE“/>
</VersionRange>
</UpgradeActions>
</Feature>
- Double-click your feature and change the version to version 2.0.0.0
- Right click your project and chose Package to package your solution
Upgrade your solution and feature in the farm
To upgrade your solution in the farm can be done via stsadm, custom code or PowerShell – and since one of the coolest parts of Sharepoint 2010 is Powershell, find your favorite PowerShell Editor (I User PowerGUI) and fire the following Powershell script with the path to your solution and the name of your solution
Update-SPSolution -Identity TheUpgradeableCT.wsp -LiteralPath C:\devprojects\TheUpgradeableCT\TheUpgradeableCT\bin\Debug\TheUpgradeableCT.wsp –GACDeployment
This alone isn’t enough to upgrade it – you to call a certain method to upgrade your feature – and this can be done via psconfig or custom code in any way you prefer….and I prefer the code attempt, so fire up a new instance of Visual Studio 2010 and make yourself a Console application (remember to change it to 64 bit build and reference Microsoft.SharePoint.dll):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
namespace UpgradeTheContentType
{
class Program
{
static void Main(string[] args)
{
using (SPSite currentSite = new SPSite(“http://intranet”))
{
foreach (SPFeature feature in currentSite.QueryFeatures(SPFeatureScope.Web,true))
{
if (feature.Upgrade(false) != null)
{
Console.WriteLine(“Feature “ + feature.DefinitionId.ToString() + ” failed to upgrade!”);
}
else
{
Console.WriteLine(“Feature “ + feature.DefinitionId.ToString() + ” was successfully upgraded!”);
}
}
}
}
}
}
This bit of code queries every feature at the web scope at http://intranet for features in need of an update and actually tries to update them

So that’s all…check your content type and your list instance for the new field – which should be present. In the next post I will make the FeatureUpgrading of the FeatureReceiver a bit clearer. Until then the code is available at my DropBox at http://dl.dropbox.com/u/6050844/Blog/UpgradeContentTypes.zip
Have fun
Peter






