Versioning and upgrades in custom modules

June 28, 2012 Digital Experience

There are two types of modules in Sitefinity – static and dynamic. Dynamic modules are much easier to work with and we recommend you use those, unless you have very specific requirements that are not supported (hierarchies, complex data models, integrations with other systems). There are still cases where customers use static modules and we often get questions about them. This blog post will explain how Sitefinity installs static modules and how you can take advantage of this process to upgrade older versions that are already used.

What is a module upgrade?

In most cases it is safe to assume that you’re starting to build a Sitefinity module from scratch. However, this is not always the case. As vendors of a product that needs to be upgraded on customer premises, we know this well. As a module developer, you might want to sell your module to third parties or change/add functionality when it is already working with live data in production. This changes after your module has shipped are what we call a module upgrade. Although the code for your module is always replaced, sometimes you need to change the schema and data that your module manages.

The module class – your module entry point

Apart from the data model and API of your module, you always need to create a module class. This class is how Sitefinity knows that you actually have a module – it is your module’s entry point. There are three important member methods that take part in the installation and upgrade of a module - Install, Initialize and Upgrade.

  • Install – called the first time your module is installed
  • Initialize – called on each application start
  • Upgrade – called when the version of your module changes

To understand how to implement those methods, first you need to know how Sitefinity uses them when stating up all modules.

Sitefinity module startup

When the Sitefinity application starts, it goes through all registered modules in configuration and decides whether they should be installed or upgraded, according to the above flowchart.

Entries for all registered modules in the configuration look like this:

<systemConfig xmlns:config="urn:telerik:sitefinity:configuration" xmlns:type="urn:telerik:sitefinity:configuration:type" config:version="5.0.2860.23119" build="2860" previousBuild="2800">
    <applicationModules>
        <add title="Real Estate" type="Telerik.StarterKit.Modules.RealEstate.RealEstateModule" startupType="OnApplicationStart" version="1.3.4562.23178" name="RealEstate" />
    </applicationModules>
</systemConfig>

As you can see, all decisions involve the current version of the module stored in its configuration element. The first time Sitefinity installs your module, it will set the version to the version of the module assembly. From then on, you can control when the upgrade method for your module gets called by managing the version of the assembly.

Managing your module assembly version

By default, when you create a class library project in Visual Studio, the assembly version is static and is set to 1.0.0.0. You can change this from the AssemblyInfo.cs file, under Properties. For Sitefinity assemblies, we always manually set the major and minor version. The build number is automatically incremented. You can do the same for your custom modules.

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.*")]

Note: For more information you can read Assembly Versioning on MSDN.

Implementing the Upgrade method of the module class

Once you have control over the assembly version of your module, you can use that to execute custom logic whenever you module is upgraded. When Sitefinity calls your Upgrade method, it always supplies the old version in an argument.

You as the developer of the module should know what changes you’ve made between different versions and execute code that updates your model to work with the newer version. It might be the addition of a new persistent class or property of an existing one, a new relation between persistent items, etc.

public override void Upgrade(SiteInitializer initializer, Version upgradeFrom)
{
    if (upgradeFrom.Build > 2500)
    {
        // upgrading from 5.0
    }
    if (upgradeFrom.Build > 2800)
    {
        // upgrading from 5.0 SP1
    }
    if (upgradeFrom.Build < 1800)
    {
        // upgrading older versions - change schema
    }
}

This method gives you control over what happens when someone replaces your module assembly with a new one. We advise everyone who submits modules to the Sitefinity marketplace to use these versioning mechanisms. They makes managing upgrades much easier and prevent any need to communicate directly with the users of your module for detailed instructions. If all this seems too complex, this is yet another reason to use dynamic modules. They have no need of upgrades and similar scenarios are handled seamlessly by Sitefinity.

The Progress Team