Feature Upgrade and Versioning

Hello,

SharePoint Foundation introduces the “Feature Upgrade” capability allowing to developers to upgrade their already installed features and to add new items or modules to already deployed solutions. This way we can extend SharePoint applications with more functionalities that were missing in the first version or simply change something to get a new version that meets our needs.

I tried to figure an example that can make sense to the “Feature Upgrade and Versioning” as a topic that I will be talking about in this post and through which we can explore and use, at the same time, all the technics that SharePoint offers to upgrade already deployed solutions and applications, generally speaking.

So, first of all (1) we will build and deploy our demo list with a content type, the list is called “Projects”, it includes just few simple fields to manage and save details about projects, then, assuming that we still need another field whatever was the reason (2) we will try to add this missing or required field to the list. Assuming then that the default list forms, generated by SharePoint, don’t meet any more our needs so, (3) we will develop and use new custom forms. That’s it! We start with a simple list, just few fields and just the default generated forms and we will go through the upgrade scenarios, to get a new version of our list, with all what we need.

I think that should be sufficient as an example to explain ”how” can we use the feature upgrade or even “why” do we need to use it in our real world projects. I still think that we all got this question in mind the first time we heard about feature upgrade and versioning.

The plan will be the following :

1)  Preparing our demo Sample

2)  First upgrade scenario : ApplyElementManifests and AddContentTypeField to add the new required field

3)  Second Upgrade Scenario : CustomUpgradeAction to define the new custom forms as the default forms used in this list

4)  MapFile – What about it ?!

5) Feature Upgrade Object Model

That’s it ! Now you can launch visual studio and try to achieve the following steps, as explained below.

1)  Preparing our Demo Sample

Our solution is the following:

1

I started with an empty SharePoint Project that will be deployed as farm solution. Just to keep things organized I’m using folders. So we need first of all to define the list columns, then to create the “ProjectsCType” content type in which we need to reference these columns. Once we got the content type we need to create the “ProjectsLD” list definition from content type, based on the “ProjectsCType” content type as you can guess. Finally add a list instance, called “Projects” in our demo, that gets its definition from the “ProjectsLD” list definition. It’s simple until now.

The defined columns are shown below :

2

Refer to my post if you still need to learn how to build a list definition with a content type using visual studio.

I renamed the “Title” field. Now it’s called “Name” in our Demo. (Refer to this post if you don’t know how to do that, otherwise this step is optional you can keep the default column display name).

I’m using two features to deploy the project elements. One site collection scoped feature called “Content Types and Fields” that contains the site columns and the content type.

The second feature is web scoped, it’s called “List Definitions and Instances” and it contains the list definition and the list instance as shown below.

3

Once done, build and deploy the solution. Check the site that you used for debugging and you will find our “Projects” demo list.

4

Until now we have prepared our demo list, we are ready to go through the upgrade scenarios.

2)      First upgrade scenario : ApplyElementManifests and AddContentTypeField to add the new required field

As we can see, the current “Projects” list contains 5 columns (the Project Name, the Code, the Client, Start Date and End Date). We still need another column to save a brief description of the project. We will upgrade our list to add the “Description” new field.

Allow me to explain how to proceed or, what I mean, where to add items exactly in the solution.

We need to add a new column to the “Projects” List. Our list definition uses the “Projects” content type. In such situations we need to use “AddContentTypeField” to add the new column to the content type referenced in the list definition. So there will be two required steps :

Define the new site column called “Description”.

Add this column to the “Projects” content type so it will be automatically added to the “Projects” list fields once the solution is updated and the feature is upgraded.

Let’s do it!

Add a new empty element to the “SiteColumns” folder. I called it “Fields_Version_1.0.0”. Double click this item and define the “Description” new field as I did below. (Don’t care about the layouts mapped folder we don’t need it until now)

5

Double click the “Content Types and Fields” site collection scoped feature. Make sure that it contains the item called “Fields_Version_1.0.0”. Click the “Manifest” tab in the feature designer, then “Edit Options” and “Open in Xml Editor”.

61

Now we will configure our feature. There will be 2 required steps to do :

(a)    Increment the version number of the feature. By default the version assigned by default by Visual Studio is “0.0.0.0”, so we will increment it and use “1.0.0.0” for the new version.

(b)   Deploy the “Description” new site column using “ApplyElementManifests” and add it to the “Projects” content type using “AddContentTypeField”.

Use the xml editor to edit the feature and add the required “UpgradeAction” as shown in the following figure.

8

So we have incremented the version. Concerning the “UpgradeAction”, upgrade actions such as “ApplyElementManifests” and “AddContentTypeField” should be grouped in a “VersionRange” tag. We can define many “VersionRange” tags in the same “UpgradeAction”. The version of the already installed and activated feature instance that we need to upgrade is “0.0.0.0” so it should be included in the “VersionRange” (greater or equal than BeginVersion and lower than EndVersion).

ContentTypeId is the ID of the “Projects” content type, the “FieldId” is the ID of the “Description” field, we need to define the “PushDown” attribute to “TRUE” so the new field will be automatically pushed down to all lists content types as part of the upgrade.

ApplyElementManifests is used to deploy the new site column called “Description”. We can deploy any other element manifests the same way, as a part of the upgrade.

Now save your changes. Select the project item from the solution explorer and click “F4” or display its properties. Change the “Active Deployment Configuration” from “Default” to “No Activation”. Build and package the project to get the final new solution file.

The next step is to update the solution installed on the server to add the missing items and the required configuration that SharePoint needs to execute when we upgrade the feature.

We can do that manually or using the “update-spsolution” command.

First of all, get the solution file. Select the project item, click “Show all files”. Select the “bin” folder then right click the “debug” folder and select “Open Folder in Windows Explorer”. We need the “.wsp” solution file, called “Feature_Upgrade_Demo.wsp” in our Demo.

9

To update the solution file already installed on the server, launch SharePoint management Shell and use the following command :

Update-spsolution –identity YourSolutionFileName –literalpath PathOfTheSolutionFile –gacdeployment

Using the solution file in our demo, and assuming that it is saved under “C:\SolutionFiles\” the command should be the following : (make sure that the path doesn’t contain spaces)

Update-spsolution –identity Feature_Upgrade_Demo.wsp –LiteralPath C:\SolutionFiles\ Feature_Upgrade_Demo.wsp –gacdeployment

This command will add the missing files on the server and update the “Content Types and Fields” feature manifest file content as shown in the following figure.

10

(If you prefer to do it manually, you just have to add the “Fields_Version_1.0.0” item and update the feature manifest file under “14\TEMPLATE\FEATURES\YourFeatureFolder”. Until now we don’t use code in the upgrade process so you don’t need to deploy the generated .dll to the GAC, any way don’t forget to make an iisreset if you did it manually, that’s required for the next step, otherwise SharePoint won’t know that there’s a new version of this feature and that it needs to be upgraded)

Once the solution is updated, we need to upgrade the site collection scoped feature called “Content Types and Fields” in our project.

We will talk about “Feature Upgrade Object Model” later, this time we will download, install and use “SharePoint 2010 Feature Upgrade Kit” which is “A set of tools for managing upgradable Features in SharePoint 2010” as described in the home page, it was developed by “CHRIS O’BRIEN”. (One of my favorite SharePoint Heroes) – http://spfeatureupgrade.codeplex.com/

Once installed, click “Site Actions”, “Site Settings” and then “Manage Feature Upgrades” link under “Site Collection Administration”. (Make sure that you have activated the required features if you don’t have the link)

11

As shown if the figure above, select the site scope, then the first option to get only features which need upgrade and click the “Search” Button. If you did correctly all the previous steps the tool will tell that the feature in which we have added the “Description” field needs to be upgraded.

Click the “Upgrade Features” button.

Now check your “Projects” list, and here we are.

12As we can see the “Description” field is now added to the list and it appears in the “Projects” list’s new form.

You can use the tool that we have just installed to check the current version of the feature, this time select the second option “All Features” and click “Search” button again, we can see that is was upgraded. The version number is now “1.0.0.0”.

13_1

3)      Second Upgrade Scenario : CustomUpgradeAction to define new custom forms as the default forms used in the “Projects” list

Assuming now that we need more customized forms for our “Projects” list with for example, more validation rules or if you want to apply another look and feel ….whatever was the reason, we need to develop and assign new custom forms for the “Projects” list. That’s what we will do in our second upgrade scenario.

As shown in the following figure, we have added 3 application pages to be deployed to the “Layouts” mapped folder. These are the custom forms to be used in the “Projects” list. (There’s no style sheet or java script files in the project because I will just show you how to change the “Projects” list default forms as a part of the upgrade process I’m not interested about how these forms will look – sorry I have no time for that)

14

Now we need to add the upgrade required configuration and code to be executed when we choose to upgrade the feature. This time we are interested about the web scoped feature that deploys the list definition and the list instance, it’s called “List Definitions and Instances” in our Demo.

So double click this feature and edit its manifest file to add the following Upgrade Action with the required parameters to be used in the code.

15The version of the already activated feature instance is “0.0.0.0” as we said and since it was not upgraded in the first scenario so we can use “1.0.0.0” for this new version.

The “CustomUpgradeAction” is used with code to be executed when we upgrade the feature. We can add many custom upgrade actions that’s why we need to use the name attribute to identify the upgrade action.

We need to know, as you will see later, the name of the list and the content type for which we will assign the new custom forms and the Url of these 3 custom forms.

Save your changes. Right click the feature that we are talking about in the “Solution Explorer” and add an event receiver. (A feature event receiver)

We are interested about the “FeatureUpgrading” event this time. Here we add the code to be executed when we upgrade the feature.

So uncomment this function and add the following code:

public override void FeatureUpgrading(SPFeatureReceiverProperties properties, string upgradeActionName, System.Collections.Generic.IDictionary<string, string> parameters)

        {

SPWeb web = properties.Feature.Parent as SPWeb;

SPList list = null;

string newFormUrl, editFormUrl, displayFormUrl, listName, ctypeName;

switch (upgradeActionName)

{

case “ProjectsCustomForms”:

listName = (parameters[“ListName”] != null) ? parameters[“ListName”] : string.Empty;

ctypeName = (parameters[“ContentTypeName”] != null) ? parameters[“ContentTypeName”] : string.Empty;

newFormUrl = (parameters[“NewFormUrl”] != null) ? parameters[“NewFormUrl”] : string.Empty;

editFormUrl = (parameters[“EditFormUrl”] != null) ? parameters[“EditFormUrl”] : string.Empty;

displayFormUrl = (parameters[“DisplayFormUrl”] != null) ? parameters[“DisplayFormUrl”] : string.Empty;

if (!string.IsNullOrEmpty(listName) && !string.IsNullOrEmpty(ctypeName))

{

list = web.Lists[listName];

web.AllowUnsafeUpdates = true;

if (!string.IsNullOrEmpty(newFormUrl)) {

list.ContentTypes[ctypeName].NewFormUrl = newFormUrl;

}

if (!string.IsNullOrEmpty(editFormUrl)) {

list.ContentTypes[ctypeName].EditFormUrl = editFormUrl;

}

if (!string.IsNullOrEmpty(displayFormUrl)){

list.ContentTypes[ctypeName].DisplayFormUrl = displayFormUrl;

}

list.ContentTypes[ctypeName].Update();

web.AllowUnsafeUpdates = false;

}

break;

}

}

We check the upgrade action name, if it is the correct one or the one that we need here we access the defined parameters to get the name of the list, the name of the content type and the url for the 3 custom forms. Once we got all that what we need we access the list and we define these 3 custom forms as the default forms to be used in this list with the “Projects” content type.

I think that you can guess what we will do now. You do ?

So build and package the solution. Get your new solution file as we did in the first scenario.

Update the already installed one with the same powershell command (the update-spsolution command).

We will use the same application page to upgrade the feature, as we did in the first scenario. Our feature is web scoped so select the “Web” scope from drop down list, then select the first option to get only the features that need to be upgraded and click the “Search” button.

16_1

Here we get our web scoped feature that needs to be upgraded. Click the “Upgrade Features” button to upgrade it. Once done it will tell you that the feature was upgraded successfully. (If you did it correctly)

Check your “Projects” list. The new custom forms should be displayed. (Here is my display form, I’m showing only the “Name” field – for demonstration purposes – I have not finished it)

17

That’s it! Now we have the new version of our “Projects” list. We started with the first version, and then we have upgraded it to get the new one with the new “Description” field and the new custom forms.

4)      MapFile – What about it ?!

It is used like this :

<MapFile FromPath = string ToPath = string />

We can use it to rename a file during a feature upgrade :

<MapFile FromPath =”OldFileName” ToPath =”NewFileName” />

Or to change the location of a provisioned file :

<MapFile FromPath =”OldLocation” ToPath =”NewLocation” />

The problem is that it’s not working or I can’t get it to work ! I have tried too many times but I get always the same result, the upgrade action is executed successfully but nothing has changed.

I just don’t want to think that there’s something missing in my post so I will come and update this part if I get it to work. (The naughty MapFile !!)

5)      Feature Upgrade Object Model

The SharePoint feature upgrade capability is based on the following members and types that have been added to the SharePoint Object Model to allow developers to upgrade their features:

  • FeatureUpgrading event : as we have seen, this feature event receiver is raised when the feature is getting upgraded and when custom code is required for the upgrade action (when declarative technics are not sufficient to execute all the required upgrade steps).                                                                                                                                                                                                                                                 Anyway, using this event, we can access the current executing context and its properties (depending on the scope of the feature), the custom upgrade action name and the required parameters to be used in the upgrade action.
  • The “Version” attribute : “0.0.0.0” by default and if it’s not defined if the “Feature.xml” file.

The feature, whatever was its scope (Farm, Web Application, Site Collection or Web) needs to be upgraded if the current version of the activated instance is lower than the version attribute value defined in the new “Feature.xml” file. If the upgrade action is executed successfully SharePoint increments the version of the upgraded feature so it matches the version defined in the new “Feature.xml” file.

  • QueryFeatures method :

This is the missing part of the feature upgrade object model that we have not talked about until now, so it’s time to understand what it means and how to use it.

We have installed and used the “SharePoint 2010 Feature upgrade Kit” in our demo. We used it to get features that need to be upgraded, we define the scope then we click the “Search” button and it’s done, finally we just have to click the “Upgrade Features” button to upgrade the selected features.

The tool simply uses the “QueryFeatures” method with the selected scope to get a list of the features that need to be upgraded.  This method returns an “SPFeatureQueryResultCollection”. When we click the “Upgrade Features” button the tool calls the “Feature.Upgrade()” method for each of the selected features to upgrade them.

This method can be called from within an SPSite object, an SPWebApplication, an SPWebService or an SPContentDatabase.

The following code simply gets the web scoped features that need to be upgraded in the current site and adds them to a drop down list.

18

Check this method overloads here. There’s more about the feature upgrade object model too.

  • The Upgrade method

We call it to upgrade the feature, it takes one parameter of type Boolean to indicate whether to force the feature upgrade or not. Just one more detail about this method, never call it from within a feature upgrade event receiver.

That’s all about feature upgrade and versioning. I hope that was helpful!

SharePoint Custom List Definition with Content Type

Hello.

This is my first post on my SharePoint Blog.

I want to start with some basic SharePoint development technics that every SharePoint developer should be familiar with.

It’s all about lists, the famous SharePoint lists! So as a first step in the development world, we should be familiar with SharePoint development tools and templates included in Visual studio, and especially this time the List Instance, List Definition, Content Types and finally list definitions from content types.

A SharePoint list is a set of columns or fields. Adding a new item in the list means defining a value for each field or for only some fields in that item.

Sometimes we need to make things more organized and structured so we can manage too much data of different types in the same list or in different lists and keep it all working together and the most important thing to keep in mind, to get something “easy to understand” and “easy to manipulate”.

That’s why, as a best approach, I prefer to use content types with lists.

Technically speaking, we start by (1) defining our content type and the different fields that we need to include in this content type, then (2) we create a list definition that gets it’s columns from this content type, and finally, to get our list, (3) we create a list instance from our list definition.

Using this approach we can get our site scoped content type that we can use anywhere in the site collection and a list definition so we can at any time create another list instance with the same columns.

So to start:

–          Launch visual studio and create an empty SharePoint Project, define the site that you want to use for debugging

–          We will start by defining the fields that we will need to use in our content type, so we need to add a new item to the project and select “Empty Element”.

Fields should be site collection scoped elements so we can use them anywhere in the site collection and in any other sub site.

1

Double click on the added empty element to access it’s elements.xml file where we will define our fields.

2

Here we add four simple fields to get some customer details.

I also define the static name attribute that I want from the beginning so I know with which static name I will get this field from this list programmatically if we need to do so.

Notice that the “Country” field is not shown in the edit form, we suppose that we don’t want to allow the user to change the customer’s country once it’s added to the list, so we don’t show it in edit mode.

–          (1) Add a new item to the project, select the “Content Type” Template, we will call it “Customers”, the wizard will ask you then to choose the base content type to inherit from. Different out of the box base content types are defined so we can choose the base content type depending on what we want to create. This time and for demonstration purposes we will select the “Item” base content type.

3

We will call it “Customers” to get our Customers Content Type.

Here we need to get a reference for the fields that we have just defined, using the same ID attribute.

We can also change the name since we want to call it “Customers”.

4

As we can see, the generated content type ID starts with “0x01” (The ID of the base or Parent content type which is “Item” as described in the commented line) followed by “00” and then the last part is the new hexadecimal GUID.

Content type IDs are explained in the following msdn link http://msdn.microsoft.com/en-us/library/aa543822(v=office.14).aspx

–          (2) Add a new item to the project and select “List Definition from content type”, we will call it “Customers List”.

5

–          (3) The SharePoint Customization Wizard will ask you on the next step to define the list definition settings and if you want to add a list instance for this list definition or not.  On the dropdown list we will get all the existing content types created in our visual studio solution so we need to select the right one. Any way this time we will get only one content type, our Customers Content type.

–          We keep the last option checked to get our list instance on the site once the solution is deployed.

6

We click “Finish” to close the wizard and to get a list definition and a list instance added to our project.

Double click the list instance item to open and edit/add, if we need it’s definition attributes.

7

I changed the Title and the Url to get something more meaningful and easy to remember or to type as the url.

Double click the elements.xml file to open and edit the settings of the list template.

8

Read the comment below the elements tag to remember or to get sure that you will not change the value of the name attribute :p, otherwise you will get an error if it does not match the folder name of the list definition project item which is “Customers List” in our sample.

I added the “DisallowContentTypes” attribute and defined it’s value to false so content types can’t be managed on lists created throw this list definition, otherwise we can make “TRUE” if we don’t want to do so.

Finally open the “Schema.xml” file to edit it’s content and finish all this work.

9

Some attributes are easy to understand such as:

  • Title : the display name of the list
  • FolderCreation : to allow the creation of folders in this list or not (new folder command will be displayed in the new menu or not)
  • EnableContentTypes : I added this attribute and defined it’s value to TRUE because we need to use the customers content type
  • Name : is the internal name of the list
  • Url : the site relative url of the list

ContentTypes tag contains the content types that will be used in our list.  It’s the same content type definition that we have created.

The next tag “Fields” contains the fields that we have created at the beginning in the empty element.

“Views” then defines the views in this list, here we need to add or to reference the fields that we want them to appear in the default view (the second one with the attribute “DefaultView=”TRUE”), so add the fields references in the “ViewFields” tag.

10

 

I deleted the “LinkTitle” field reference because I don’t want that field to appear in my default view.

The “Query” part means that items in this view will be displayed and ordered by the ID column.

The last part “Forms” define the different forms that will be generated and used with this list. (Display Form, Edit Form and New Form”).

That’s it !!! so I just want to finish with one last detail.

I don’t know if you have noticed in the previous photo the two windows already opened in my visual studio “List Definition and Instance.feature” and “Fields and Content Type.feature”, if you really did and now you are wondering what they are doing and why I kept them in my screen, it’s OK I will tell you.

Visual Studio or custom content created with visual studio is deployed to SharePoint site through features. When we added our first empty element to define the fields VS have automatically added a feature to deploy this item to SharePoint. So to do things as they should be done, and because I love to do so and as a good practice, I added a second feature to my project, I renamed the two features to give them more meaningful names.

The first one (F1),is called “Fields and Content Type.feature” and it contains the empty element used to create the fields and the content type that reference them. It should be a site scoped feature so we can use these fields and this content type anywhere as I said in our site collection.

The second one (F2) is called “List Definition and Instance.feature” and it contains as its name indicates the list definition from our customers content type and the list instance that we will find once we deploy the solution. This one should be a web scoped feature because we need to use this list and to find it’s template in our site.

We can also change the title and the description of the feature so we can remember or understand what it should do every time we will activate or deactivate it.

(F1)

11

(F2)

12

 

That’s it! Now I just need to deploy my project to get it all in my site.

Check your quick launch menu and there’s our famous “My Customers” list.

13

 

As we can see the fields that we defined in the “ViewFields” section in the schema.xml file appears in the default view.

The title field does not appear in the default view but it appears in the list forms (new, edit and display form). We don’t often need it with that name so I will make another post the next time to see what we can do with that field.

Just to show you all what we got installed on our SharePoint site.

Our site collection scoped feature “Customers Content Type and Fields”. Click “Site Actions”, “Site Collection features” under “Site Collection Administration” to access the list of site scoped features.

14

 

Our web scoped feature “Customers List Definition and List Instance”. Click “Site Actions”, “Manage Site Features” under “Site Action” to find it.

15

 

Click “Site Actions”, “Site Settings” and “Site Columns” under “Galleries” to view the fields that we created within the empty element at the beginning.

16

Click “Site Content Types” under “Site Columns” to see the “Customers” custom content type under “Custom Content Types” group.

And finally, click “Site Actions” menu, “More Options” and “List” menu to access the list templates installed on the site, and here we find our “Customers List” template. Now we can easily create another list with a different name but with the same columns.

17

 

 

Every time a list is instantiated from this list template, it will be using the “Customers” content type.

18

I stop here! I hope that was helpful and easy to understand. It’s not just about list definitions and content types, this time you learned, from only one tutorial, how to deploy custom fields to the site with an empty element, how to create a custom content type and then a list definition that gets it’s columns from it, how to create a list instance and define the fields that will appear in the view and one more thing, the most important thing, how to use features to deploy custom development work to SharePoint and how features are scoped and even how to do to get things more organized, structured and easy to manipulate even for the end user. If you really understand all that and you feel exited to see something more interesting, in my opinion you should stop reading, you take a coffee or something like that and imagine how we can use these simple steps to get into something more complicated as a real world project.

Me, I will take a coffee too but this time I don’t want to do so, just a coffee lol.