Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

We're working on a SharePoint 2010 publishing site that has been deployed to our client's environment. We need to add 5 new site columns and add them to one of the content types (that's based on Page).

Typically we would do this through the feature upgrade route, but we're seeing the same issues that I'll be describing in this question, so we decided to step back and try something really simple.

We added the site columns declaratively through CAML and upgraded our WSP. We've always found that new site columns don't appear immediately in the Site Columns collection, deactivating and reactivating the containing feature fixes that.

The next step is to add the columns to the content type using the UI. We do this and check the checkbox that says "upgrade all content types based on this content type". This takes an unusually long time, approximately 20 to 25 minutes. Afterwards, the columns appear on the content type.

However, when I go to a page library deep in the site that contains pages based on this content type, I don't see the columns. If I go the Page Library settings and choose the content type that's bound to the Pages library (through a content type binding), the columns do not appear in the list of columns of the content type.

If I try to add the columns, I get a SharePoint exception that they already exist. The problem is the corresponding Publishing page layout doesn't see the columns on the content type.

We see the exact same behavior when trying to do this via a feature upgrade, so we decided to try this simple approach instead to try and isolate the problem.

Appreciate any tips!

share|improve this question
1  
Dont have an answer, but I would start with inspecting the content type, list settings and the fields via PowerShell. (Since you get the error site columns already exist...) $s = get-spsite "http://..." $w = $s.rootweb $lists = $w.Lists["listname"] $contentType = $w.ContentTypes["contentTypeName"] Then inspect the contents of those and see if the SPFields (ie site columns) are there. Have you also tried, activating/deactivating your feature, iis reset etc? –  vasya10 Apr 26 '12 at 14:33
    
vasya10, when I run this PowerShell on a subsite that contains pages using the content type, .Fields and .ContentTypes are empty. –  George Durzi Apr 26 '12 at 16:58
1  
Found an approach that works. It's kind of stupid so I hesitate to call it answer; we found it by trial and error. Using either PowerShell or the SharePoint UI, if we add a site column to the content type, remove it, and then add it again, it propagates properly. See? Stupid. –  George Durzi Apr 27 '12 at 17:14

3 Answers 3

I recommend watching this excellent screencast on feature upgrading by Jeremy Thake. Helped when I struggled with a similar issue. I ended up writing feature upgrade actions in CAML using the AddContentTypeField to add fields to content types, in addition to updating the site content type via PowerShell. Did the trick.

I would also recommend reading the answers of this post on updating content types.

share|improve this answer
    
tarjeieo, when I've had success using the feature upgrade process, I only specify the AddContentTypeField in the UpgradeActions. Why do you also have to update the site content type via PowerShell? –  George Durzi May 4 '12 at 14:40
    
@GeorgeDurzi I don't know why, but it worked for me to replicate the changes to the list content types... –  tarjeieo May 4 '12 at 15:16
    
All-in-all my experience of the upgrade process is that it's still a little flakey in places. Some of it works great, while other bits, especially content types and columns that need to propagate do not work quite so well. The object model/powershell approach is definitely more robust at the moment imho. –  Steve May 21 '12 at 11:40

Combination of SharePoint site columns and content types is somewhat tricky when you need to add new columns to existing content types on existing site.

When you add a column to list from site columns, it is actually a copy of site column, not a reference, so when a site column gets updated, the changes are not propagated to columns in lists automatically. A content type however includes only column references, not columns themselves.

The following scenario works if you need to add a new column to existing content types through Element.xml:

  1. Change xml definition for site columns.
  2. Deploy new wsp solution
  3. Deactivate and activate again the feature that includes that column definition. Now the new column will be available in Site columns.
  4. Add new column to site content type and ensure to propagate update to children. After this stage the field reference will be added to all content types that are children of the updated content type (this includes content types in lists as well, but it will be still invisible in the UI before you perform the next step). This stage usually takes quite long time especially if your content type is used in many list on the site collection.
  5. You need to add that new column to lists as well, and one need to do it for each list separately (i.e. Go to list settings, choose "Add from existing site columns" option and choose your newly added field). After this step you will see column reference on list content types as well and you will be able to use it.

It should be possible to automate some stages, especially the last one if you have a lot of lists that are using your content type. Here is an example of powershell script to perform steps 4 and 5, it could be easily extended to add several columns simultaneously:

function AddFieldLink($site)
{
    $web = $site.RootWeb

    $ctId = New-Object Microsoft.SharePoint.SPContentTypeId($ctIdString)
    $ct = $web.ContentTypes[$ctId]
    $needUpdate = $false

    if ($ct.FieldLinks[$fieldName] -eq $null)
    {
        $field = $web.Fields.GetFieldByInternalName($fieldName)
        $fieldLink = New-Object Microsoft.SharePoint.SPFieldLink($field)
        $ct.FieldLinks.Add($fieldLink)
        $needUpdate = $true
    }

    if ($needUpdate)
    {
        # Updating content type with propagation to all children. This could take several minutes (seriously!)
        $ct.Update($true)
    }
}

function AddFieldToLists($site)
{
    $field = $site.RootWeb.Fields.GetFieldByInternalName($fieldName)
    if ($field -ne $null)
    {
        $ctId = New-Object Microsoft.SharePoint.SPContentTypeId($ctIdString)
        $ct = $site.RootWeb.ContentTypes[$ctId]
        $usages = [Microsoft.SharePoint.SPContentTypeUsage]::GetUsages($ct)
        $totalUsages = $usages.Count
        $i = 0
        foreach ($usage in $usages)
        {
            $i++
            $statusText = [string]$i + " of " + $totalUsages + " - " + $usage.Url
            Write-Progress -Activity "Processing lists" -Status $statusText -PercentComplete ($i / $totalUsages * 100)
            if ($usage.IsUrlToList)
            {
                $web = $null
                try
                {
                    $web = $site.OpenWeb($usage.Url, $false)
                    $list = $web.GetList($usage.Url)
                    $needUpdate = $false
                    if (!$list.Fields.ContainsField($field.InternalName))
                    {
                        $list.Fields.Add($field)
                        $needUpdate = $true
                    }

                    if ($needUpdate)
                    {
                        $list.Update()
                    }
                }
                finally
                {
                    $web.Dispose()
                }
            }
        }
    }
}

$ctIdString = "0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900f1da382487b744a9a8b927118654da50" # you content type id goes here
$fieldName = "YourFieldNameHere"

$site = Get-SPSite "you site collection url"
AddFieldLink $site
AddFieldToLists $site
$site.Dispose()
share|improve this answer

first of all, deactivating then re-activating your feature to get your columns is not how the upgrade works. If you're deploying an upgrade as part of a farm solution you have to manually run the upgrade using Powershell (whereas sandboxed solutions run automatically) some background and commands can be found here: http://www.sharepointnutsandbolts.com/2010/08/feature-upgrade-part-5-using-powershell.html (and Microsoft also published a script to do this which I don't have the URL for).

We've had problems too with pushing new columns out which doesn't appear to propagate properly - the approach to you commented does work and is how we finally did our upgrade, so you're not the only one, despite how stupid it appears to be!

share|improve this answer
    
Steve, let me clarify about the deactivate/activate. New site columns don't appear in the site collection after upgrading the solution unless I deactivate/activate the feature that contains them. I don't expect the new columns to get added to the content type by deactivating/activating. –  George Durzi May 4 '12 at 14:39

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.