Archive for April, 2010

Versioning and upgrading your features with SharePoint 2010 Application Lifecycle Management (ALM)

30. April 2010

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

  1. 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
  2. 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.
  3. Paste the following into the elements-file created in your content type node – this will create a basic document content type

<?xml version=1.0encoding=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>


  1. 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

  2. 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:

  1. 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.0encoding=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>

  1. 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.
  2. 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″.
  3. 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
  4. 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.0encoding=utf-8 ?>
<Feature xmlns=http://schemas.microsoft.com/sharepoint/>
<UpgradeActions>
<VersionRange BeginVersion=1.0.0.0EndVersion=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>

  1. Double-click your feature and change the version to version 2.0.0.0
  2. 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

PowerShell and Sharepoint 2010 – Part 2 : Reading the ULS log

20. April 2010

Some part of problem solving in Sharepoint is done through the ULS logs which by default is placed in the Logs-directory of the RootFolder of your Sharepoint installation. In Sharepoint 2007 you need to manually search the text-files for the terms that might have caused problems for the user and then try to connect the event log and the uls-logging times and figure out what happened. While this is still the truth in SharePoint 2010 PowerShell has made it increasingly easier to scan the log for whatever error you might have. So grab a PowerShell command prompt and type Get-SPLogEvent and watch the complete ULS appear across your screen. This is not very helpful and takes a bit of time, so we need to do some filtering.

Date and time filtering

First of all we need to do some date-filtering. If you only want errors from the last five minutes, you can filter by giving the command a start property in a format like the following: Get-SPLogEvent –StartTime (Get-Date).AddMinutes(-5) which obviously will take and calculate a start time from current time (which is provided by the get-date method, and the add negative five minutes, which will give the log for the last five minutes. Note that an endtime is available in the exact same way

Chosing what columns to see

Still I get no idea, what the error is – only stuff like EventID, The time the error occurred and stuff like that appeared in the above command. This must be available in a more detailed form. And of course it is. By sending the results of the Get-SPLogEvent command into a select statement, you can choose exactly what columns to show. So grab the PowerShell command again and write Get-SPLogEvent –StartTime (Get-Date).AddMinutes(-5) | select timestamp, message and you will get the timestamps and messages of all messages from the last 5 minutes. Available columns are:

  • TimeStamp
  • Continuation
  • Process
  • ThreadID
  • Area
  • Category
  • EventID
  • Level
  • Message
  • Correlation
  • Context

 

So a select * instead of select message will return every field in a format not very nice J

So final thing is to decide what columns you like, grab them and format them in a usefull way. Format-table I excellent for this, and passing the following command is often usefull: Get-SPLogEvent –StartTime (Get-Date).AddMinutes(-5) | select * | Format-Table –Wrap

Filtering on these fields

A filtering on any of the fields above is available to prevent admins from looking at everything, when they have an idea of where to look. Especially the new correlation id is handy to filter. It is provided on nearly any error message in the user interface and provided again in the log files. If you want to query the logs for a specific error you can do it by providing the SPLogEvent –StartTime (Get-Date).AddMinutes(-5)| Where-Object {$_.Correlation –eq “yourFancy CorrelationID”} | select timestamp, process, level, message, correlation | Format-Table –Wrap

Have fun J


Follow

Get every new post delivered to your Inbox.