How to add a new Site Column to an existing Content Type from code
This post describes how to create a new column, add it to an existing Content Type in an existing feature and last run an upgrade in PowerShell of the feature.
Feature.xml file:
<?xml version="1.0" encoding="utf-8" ?>
<Feature xmlns="http://schemas.microsoft.com/sharepoint/" Version="2.0.1.0">
<ElementManifests>
<ElementManifest Location="NewColName\Elements.xml" />
</ElementManifests>
<UpgradeActions>
<VersionRange EndVersion="3.0.0.0">
<ApplyElementManifests>
<ElementManifest Location="NewColName\Elements.xml" />
</ApplyElementManifests>
<CustomUpgradeAction Name="AddFieldToContentType">
<Parameters>
<Parameter Name="FieldId">x-x-x-x-x</Parameter>
<Parameter Name="ContentTypeId">xxxx</Parameter>
<Parameter Name="PushDown">TRUE</Parameter>
</Parameters>
</CustomUpgradeAction>
</VersionRange>
</UpgradeActions>
</Feature>
The NewColName\Elements.xml contains the definition of the new column and shall be added in both the ElementManifest section and the UpgradeActions-ApplyElementManifest section. The ElementManifest section is used when deploying the feature the first time, and the UpgradeAction section is used when upgrading the feature. The new version of the feature is 2.0.1.0, and the upgrade action shall be active until version 3.0.0.0 (EndVersion attribute).
The CustomUpgradeAction refers to an upgrade action named "AddFieldToContentType". The action takes three parameters the new field ID the existing Content type ID and a parameter called PushDown, witch configures of the Content Type changes shall be pushed down to child Content Types.
The new column is defined in NewColName\Elements.xml:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Field
Name="NewColName"
StaticName="NewColName"
Type="Text"
Required="FALSE"
DisplayName="NewColName"
Description="The new column"
Group="NewGroup"
ID="{x-x-x-x-x}"
Overwrite="TRUE" OverwriteInChildScopes="FALSE"
SourceID="http://schemas.microsoft.com/sharepoint/v3"
xmlns="http://schemas.microsoft.com/sharepoint/" />
</Elements>
Create an event receiver and override the FeatureUpgrading method, this method is invoked when the feature is upgraded (surprise!) and the upgrade action name is taken as a parameter:
public override void FeatureUpgrading(
SPFeatureReceiverProperties properties,
string upgradeActionName,
System.Collections.Generic.IDictionary<string, string> parameters)
{
if (properties.Feature.Parent is SPSite)
{
SPWeb web = ((SPSite) properties.Feature.Parent).RootWeb;
switch (upgradeActionName)
{
case "AddFieldToContentType":
string fieldId = parameters["FieldId"];
string contentTypeId = parameters["ContentTypeId"];
bool updateChilds = true;
bool flag;
updateChilds=bool.TryParse(parameters["PushDown"],out flag);
AddFieldToContentType(web,contentTypeId,fieldId,updateChilds);
break;
default:
break;
}
}
}
AddFieldToContentType method:
private void AddFieldToContentType(SPWeb web, string contentTypeId, string fieldId, bool updateChilds)
{
SPContentType type = web.ContentTypes[new SPContentTypeId(contentTypeId)];
type.FieldLinks.Add(new SPFieldLink(web.Fields[new Guid(fieldId)]));
type.Update(updateChilds, updateChilds);
}
The last thing to do is to override the FeatureActivated method, this method is invoked when the feature is activated and it will make sure that the new Field also is added to the Content Type the first time the feature is activated:
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
if (properties.Feature.Parent is SPSite)
{
SPWeb site = ((SPSite) properties.Feature.Parent).RootWeb;
const string fieldId = "x-x-x-x-x";
const string contentTypeId = "xxx";
AddFieldToContentType(site, contentTypeId, fieldId, true);
}
}
So to upgrade the feature run this script in PowerShell :
$versionFolder = "C:\temp\"
$solutionName = “x.wsp”
$solutionPath = $versionFolder + $solutionName
$siteUrl = "http://.../"
$featureId = "{x-x-x-x-x}"
Update-SPSolution –Identity $solutionName –LiteralPath $solutionPath –GacDeployment
# wait for it to finish
$site = get-spsite $siteUrl
$feature = $site.Features | where {$_.Definition.Id -eq $featureId}
if($feature)
{
$ex = $feature.Upgrade($true)
Write-Host $ex #if anything went wrong this is printed
}





