WebTemplate training materials – Lab 4 – Upgrading existing sites with feature versioning


Updated on 14th of March 2012

This post is lab 4 from series of training materials for WebTemplate creation and maintenance. Please check the following posts for details and other exercises. Notice that you can download full package with all required lab material from link available in introduction post. This package contains all supplementary materials and labs in word format.

This particular post will concentrate on following functionalities.

  • Creating application page to site settings to manage feature versions
  • Update previously deployed content type by adding new field to it
  • Creating feature upgrade definitions for the existing features to update existing sites

Lab 04 – Life cycle management for WebTemplate created publishing sites

The project files for this lab are in the ‘C:\Student\Labs\04_Lifecycle’ folder

Lab Objective

Lab Overview: In this lab you will update existing sites using feature upgrade definition.

Additional Resources

This lab includes the following additional resources:

Starter Files


Files that can be used to help complete the labs.

Source Code


Completed lab source code after this exercise

Solution structure


Solution structure started in previous exercise.

Getting Started

Notice that all code and xml elements which are meant to be copied are available as text in the Word documents. This means that if you need to copy any of those elements, it’s better to use Word document formats of these labs.

This Hands-On Lab contains a number of additional resources in fixed locations. By default, it is assumed that the base HOL directory is C:\Student and that the labs and additional resources are located under this directory.

The default working folder for this lab is C:\Student\Labs\04_Lifecycle.

Please notice that this exercise is assuming that you have environment with url http://intranet.contoso.com in your usage. If you use some alternative url, you’ll have to update scripts and use correct entries in exercises to make exercise to work properly.

Lab Setup Instructions

In the lab setup you will execute a PowerShell script that will create a new SharePoint site collection.

1. Start the Virtual Machine in Hyper-V.

2. Log on to the Virtual Machine as the local administrator with a user name of Contoso\Administrator and a password of pass@word1.

3. Open Windows Explorer and browse to the location C:\Student\Labs\Contoso.Intranet, in the folder double click Contoso.Intranet.sln to start the previously created solution structure.

  • This step assumes that you have already created lab 1, 2 & 3 based on the lab guidance’s, so that we can continue building up the customization package.
  • Notice also that package contains full source code status after lab 3 in folder C:\StudentWebTemplate\Labs\03_WCM\Solution\Contoso.Intranet – Lab 3 which you can copy as your starting point if you want to skip previous labs completely.


Exercise 1 – Creating upgrade application page

In this exercise we will create simple application page to list features, which could be upgraded. This exercise will familiarize you to feature framework object model and how we can use that for upgrading features granularly. Notice that depending on the actual deployment, you might actually want to upgrade your features using PowerShell, not by adding this kind of additional application page to site settings page also to avoid accidental upgrades by other end users.

Task 1 – Adding custom application page to solution

1. Expand Layouts folder in the Solution Explorer

2. Right click Contoso.Intranet folder and choose Add – New Item…

3. Choose Application Page template and name it as UpgradePage.aspx


4. Click Add

5. Locate ContentPlaceHolder with the Id PlaceHolderMain

6. Update place holder as in the following code snipped to include two different tables


7. Save changes

8. Open Upgradepage.aspx.cs file under the aspx file

9. Add following using statements


10. Add override for CreateChildIControls method as follows below the Page_Load method · Notice that we use QueryFeatures method to query features which can be upgraded


11. Add following DisplayFeature method below the CreateChildControls method


12. Add btnUpgrade_Click event handler below DisplayFeature method


13. Right click the SPIs folder in the solution explorer and choose Add – New Folder

14. Name folder as CustomActions

15. Right click CustomActions folder and choose Add – New

16. Choose Empty template and name it as FeatureUpgradeSiteSettings and click Add

17. Update the Elements.xml file for the custom action as follows


18. Update feature association for the just added custom action FeatureUpgradeSiteSettings so that it’s activated in the SiteMainResources feature


19. Open SiteMainResources feature and use properties window to set the version to


20. Right click Contoso.Intranet and choose Deploy

21. Move to address http://intranet.contoso.com

22. Move the Site Settings from the Site Actions

23. Click Site collection features under the Site Collection Administration

24. Activate Contoso.Intranet Site Main Resources feature

25. Move back to Site Settings page and ensure that the Site Collection Feature Upgrade link is present under the Contoso Configuration


26. Click Site Collection Feature Upgrade link is present under the Contoso Configuration to ensure that code is working properly

  • Page should list all activated features in site collection scope and their version
  • Notice that look and feel depends on which master page has been enabled for the system pages.


Task 2 – Updating features and content types

1. Move back to Visual Studio side

2. Expand SPIs folder, right click SiteColumns and choose Add – New Item

3. Choose Empty Element and name it as v2Fields


4. Update the Elements.xml as in the following code snipped


5. Save changes

6. Expand Features node and open up Contoso.Intranet Site Main Resources feature

7. Associate the v2Fields to Contoso.Intranet Site Main Resources feature. You can use packaging explorer to ensure the current associations.

  • This is done for new site collections, so that now added field is added automatically when new sites are created. Steps to modify existing sites will follow up later in this exercise.


8. Expand SPIs folder and ContentTypes folder in the solution explorer

9. Open Contract content type element.xml file and review the content – notice that our field is not present and it should not be added here either


clip_image014[1]Upgrading content types – what to do and what not to do?


You should NEVER EVER update content type definition which has been already deployed to any site collection. This would not result outcome you’re looking for. When we are updating existing content types, we’ll need to do two different things.

Update initial definition for new site collections – even for this, you should not update actual ContentType definition, since that would break reference to it from existing site collections. What we’ll need to do is to add some code to add newly added field to existing site collection from feature receiver.

Update existing content types – Most reliable way to do this also by using code – by adding required changes to feature upgrade method, which is called when feature is upgraded to latest version.

We’ll cover both approaches in following steps in this exercise.

10. Open Page content type element.xml file and review the content, notice hat our new field is not present and should not be added here either


11. Let’s start by handling upgrade scenario for existing site collections. Expand the SiteMainResources feature node and open up SiteMainResources.Template.xml file by double clicking it


12. Update the template file as follows, so that there’s few upgrade actions to perform, when we upgrade from previous version to newer one

  • Notice that we use one out of the box feature upgrade action and then we’ll include two custom feature upgrade actions to handle more specific updates on our existing site collection.


13. Update [PAGEID] and [CONTRACTID] stamps in the just copied xml element with the proper identifiers. You can locate the ID’s from the following locations. These refer to unique identifiers of the content types in following files:

  • [PAGEID] – SPIsContentTypesPageElements.xml
  • [CONTRACTID] – SPIsContentTypesContractElements.xml

clip_image014More on feature upgrade options and techniques

You can find more information on the feature upgrade options and techniques from Internet. In this case we used ApplyElementManifest first to introduce new field to site collection. After that we are using CustomUpgradeAction element to which we write the required code in following step – in this case are also using custom upgrade action to provision newly added fields to existing content type.

There’s also out of the box element for updating existing content type declaratively, but since this element have been having some issues in certain cumulative updates, it’s more reliable to use custom code, which we will include to our feature receiver. This also gives us additional change to perform additional confirmation or code validation, if needed for the code.

14. Since we will manipulate Publishign object model, we’ll need to add reference to Microsoft.SharePoint.Pulbishing.dll

15. Right click References in the Contoso.Intranet project and choose Add Reference…


16. Move to Browse tab and move to folder C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI

17. Select Microsoft.SharePoint.Publishing.dll and click OK

18. Open SiteMainResources.EventReceiver.cs to see the content of the feature receiver

19. Add following override for FeatureUpgrading below FeatureDeactivating method


  • Notice that we place our actual business logic code for updating existing sites outside of the feature receiver, which gives us possibility to test that business logic separately without need for feature receiver deployments etc.

20. Let’s continue by adding that required business logic to our project by right clicking Contoso.Intranet and choose Add – Folder

21. Rename newly added folder as ApplicationLogic

22. Right click ApplicationLogic folder and choose – Add Item…

23. Choose Class and name it as UpgradeManager.cs


24. Your solution should be looking like in following picture


25. Open just added UpgradeManager.cs file

26. Add following using statements to file


27. Let’s also change the class to be static and include required business logic methods as follows


28. Before this class can be used in feature receiver, we’ll need to also add using statement for that, so let’s open SiteMainResources.EventReceiver.cs to see the content of the feature receiver

29. Add following using statements to file


30. Open Contoso.Intranet Site Main Resources feature in designer and use properties window to set the version to


31. Right click Contoso.Intranet and choose Build

  • Notice that until now we’ve only added code for handling upgrade of the existing structures, we’ll still need to ensure that if new site collections are created where this site collection scoped feature is activated, content types will match on latest requirements

32. To handle content type change requirements in proper way, let’s open SiteMainResources.EventReceiver.cs one more time. Let’s update the feature activated event as follows – notice that we add the required code for adding programmatically field to content types.



  • Again – just to emphasis why we did above add-in to feature activation, not on xml. This is for newly created site collections, since we should NOT be updating ContentType xml definition anymore, since we have already that used in one site collection in our environment.

33. Update [PageID] and [CONTRACTID] stamps in the just copied xml element with the proper identifiers. You can locate the ID’s from the following locations. These refer to unique identifiers of the content types in following files:

  • [PAGEID] – SPIsContentTypesPageElements.xml
  • [CONTRACTID] – SPIsContentTypesContractElements.xml

23. Right click Contoso.Intranet and choose Package

  • Note. DO NOT DEPLOY PACKAGE DIRECTLY FROM VISUAL STUDIO, since we will imitate production upgrades in following steps and if you use Visual Studio, your upgrade option is not available since Visual Studio will “try to help you” and it reinstalls features using activate/deactive commands, which doesn’t happen in actual production deployments.

24. Right click Contoso.Intranet and choose Open Folder in File Explorer

25. Move to bindebug sub folder and verify that you have compiled successful Contoso.Intranet.wsp file, which is the actual solution package to be deployed

26. Copy current path to clip board, since we need to use that in PowerShell. If you are using defined guidance, path is following – C:\StudentWebTemplate\Labs\Contoso.Intranet\Contoso.Intranet\bin\Debug

27. Open SharePoint 2010 Management Shell from Start | All Programs | Microsoft SharePoint 2010 Products

28. Run following command in the PowerShell window

  • Notice that path depends on your solution structure location

Update-SPSolution -Identity contoso.intranet.wsp -LiteralPath "C:\Student\Labs\Contoso.Intranet\Contoso.Intranet\bin\Debug\Contoso.Intranet.wsp" –GACDeployment

clip_image014[1]Upgrade or Re-deploy

In this case we used Update-SPSolution cmdlet, but you could also do retract and deploy commands in PowerShell script. Difference is that when we use update command, none of the feature installed or uninstalled methods are executed, but if you have added features to your package, those don’t get installed either.

If you use retract – deploy method, feature installed and unistalled commands will be executed and possible new features are automatically installed. Key point to notice though that both options don’t activate or deactivate features in the sites, like Visual Studio does. This is critical difference between development and production environment deployments.

29. Run command “iisreset” in the PowerShell to ensure that updated xml files will be loaded to memory

30. Open Internet Explorer and browse to site http://intranet.contoso.com

31. Make sure that front page has not been checked out – you can publish it manually before moving forward

  • This is just due the code for the feature receiver, which doesn’t have exception handling if the page has been checked out.

32. Move to Site Settings page from the Site Actions

33. Click Site Collection Feature Upgrade link under Contoso Configuration

34. Notice that the Contoso.Intranet Site Main Resources feature is listed here as possibility to upgrade


35. Click Upgrade button

  • This will execute the FeatureUpgrading event definitions (code and xml based configurations)

36. Refresh page by pressing [F5] and verify that feature is not anymore listed to be upgrade


37. Move back to Site Settings page

38. Move to Site Content Types

39. Click Contoso.Intranet – Contract and ensure that Additional details fields has been added to content type

  • You might want to verify successful update also on content type instances provisioned to existing lists, like pages list. You can do this by moving to list where content type is used and checking content type properties from list settings.


40. Move back to front page of the site and verify that web part was successfully added to the page



clip_image014[2]Upgrading features without custom application page

In this exercise we created custom application page to update feature. Depending on environment, PowerShell is much more convenient so that you have full control when upgrade is executed and nobody will upgrade features accidently just from the browser user interface.


If you find any issues on the lab, please add comments below, so that we are able to fix them as fast as possible. You can also suggest any enhancements for the lab, but due other on-going projects, I can’t promise to have time to include them. Thanks for your comments and feedback advance.

– Vesku

Comments (6)

  1. Maz says:


    Thanks for your great articles on web templates.

    I am ready to initially deploy my WSP to production but one thing on my mind is the whole issue of adding new structures and/or functionality to that WSP in response to new business requirements.

    1. Update-SPSolution seems to only be advised according to the documentation when no new files or features have been added to WSP. But I notice you have used it here and I think you HAVE added such files?  

    2. I generally feel safer using retract deploy. But can you confirm for me that if say you have a million sites created from web templates such retraction of the WSP SHOULD NOT include iterating all such sites and deactivating features then reactivating them on redeployment?  That is you just retract and uninstall the WSP and then add and reinstall the new WSP?  So that in effect once these million sites have been initially created their feature activation  event handlers are never run again. And their feature deactivation handlers are never actually run at all?  This would be my guess from reading your article and your quote

    If you use retract – deploy method, feature installed and unistalled commands will be executed and possible new features are automatically installed. Key point to notice though that both options don’t activate or deactivate features in the sites, like Visual Studio does. This is critical difference between development and production environment deployments.

    Many thanks in advance.

    Kind regards,


  2. Awesome article. Thank you.

  3. Josh says:

    Hi Vesa,

    First, thanks for the detailed write up.  Very informative and you explain the process well including what to do/what not to do at various stages.

    I realize this is a bit of water under the bridge as you posted this article a couple of years ago – but I wanted to point out what looks to me to be a slight syntax error.

    Step 19 includes a screenshot of code for the feature upgrade event.  Your line for determining your "updateChilds" value doesn't look correct.  You have the "flag" and "updateChilds" variables swapped.  I believe it should read:

    flag = bool.TryParse(parameters["Updatechilds"], out updateChilds);

    Your current code will always return true if your XML configuration property "UpdateChilds" value parses boolean value – regardless if your property's intended boolean value is true OR false.

    Thanks again – I appreciate the write up!


  4. Vesa Juvonen says:

    Thanks Josh,

    good point on the code example, feedback appreciated. This is indeed pretty old write up, but it's good to have at least the pointer in comments. I won't be however updating the package due schedule constraints, but if someone will read the post, they hopefully find your comment as well.

  5. Vj says:

    Hi Vesa,

    First of all i would like to appreciate all your efforts. I have one scenario where Document set is configured with a library which having 10 look up columns, a visual studio form and nintex workflows. All these are done through visual studio. Now we got a requirement to add 5 new filed to library and need to add some filed in Document set display form. at first i have tried to add new field using your steps, but fields are not updating and even its not showing any error. i have not designed upgrade page. i have used only power shell upgrade command. I can see in central Admin  that feature is deploying. Can you please suggest me if am doing correct or need to write any extra power shell commands.

    thank you very much in advance

  6. Vesa Juvonen says:

    Hi Vj

    Upgrade process could be tricky, but you can always check the actual versions which are executing by using PowerShell. Here's what I've been using in past during my demos for checking the version and then for updating to the right version to ensure that the upgrade actions are executing.

    # check to ensure Microsoft.SharePoint.PowerShell is loaded

    $snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}

    if ($snapin -eq $null) {

    Write-Host "Loading SharePoint Powershell Snapin"

    Add-PSSnapin "Microsoft.SharePoint.Powershell"


    # ————————————————

    # Demo on feature version resolution in farm

    # ————————————————

    $featureIdToCheck = "79b93e74-ce13-49d1-825b-5007feb8d481"

    Write-Host("Searching for feature {0}." -f $featureIdToCheck) -foregroundcolor Green

    # Check farm version details

    $f = get-SPFeature -identity $featureIdToCheck

    Write-Host("- Found feature definition named as {0} in farm with current version of {1}. Searching for feature {0}." -f $f.DisplayName, $f.Version) -foregroundcolor Green

    #Let's check feature instance versions in specific site collection

    $col = Get-SPSite -Identity http://empty.contoso.com

    $features = $col.QueryFeatures($f.Id)

    foreach ($feature in $features)


       write-host("- Found feature instance {0} within url {1} with version {2}." -f $feature.Definition.DisplayName, $col.Url, $feature.Version) -foregroundcolor Green