Inconvenient creating list instances using Feature Receivers


Recently I’ve been working with a Feature responsible for provisioning a list instance based on the Asset Library List Template (new in SharePoint 2010). In spite of the fact that everything seemed to be okay on my side (everything defined in the right place, the Asset Library Feature activated, and so on), I kept getting error that the Asset Library List Template does not exist. Finding the answer to this riddle was just a matter of… timing.

Scenario

Let me give you some more information on my scenario. I had a custom Site Definition based on the Publishing Site Definition which would by applied to a Site Collection. The Configuration section contained therefore both Site and Web Features. A part of this Site Collection’s configuration was provisioning in the Root Web an instance of a list based on the Asset Library List Template. The Feature responsible for provisioning the Asset Library List Template (Name: AssetLibrary, ID: 4BCCCD62-DCAF-46dc-A7D4-E38277EF33F4) is itself hidden and configured as Activation Dependency for the Publishing Site Collection Feature. So in order to be able to provision a list instance based on that List Template I added my custom Feature as last Site Collection Feature. Unfortunately: all I got was an error that the Asset Library List Template does not exist.

Round #1

My first suspicion was timing issue with Features and Activation Dependencies. However debugging the Feature Receiver of my Feature has proven that both Publishing and AssetLibrary Features were properly activated.

SharePoint 1 – 0 me

Round #2

If the AssetLibrary Feature has been activated how is it possible that the List Template that this very Feature provisions isn’t available? I told you that the answer was just the matter of timing, right? It is indeed.

The code I had was something like this:

SPSite site = properties.Feature.Parent as SPSite;

if (site != null)
{
    SPWeb web = site.RootWeb;
    
    SPListTemplate assetsLibrary = (from SPListTemplate listTemplate
                                    in web.ListTemplates
                                    where listTemplate.Type_Client == 851
                                    select listTemplate).FirstOrDefault();

    if (assetsLibrary != null)
    {
        SPList siteAssets = web.Lists.TryGetList("SiteAssets");
        if (siteAssets == null)
        {
            web.Lists.Add("SiteAssets", String.Empty, assetsLibrary);
        }
    }
}

The Feature I was using was a Site Collection Feature so in order to create a new List I needed a reference to SPWeb. I decided to use the SPSite.RootWeb reference since it was already there instantiated by SharePoint.

While I could try to retrieve the Asset Library List Template by its name, it’s quite risky considering all the different names in all the different languages. Instead I used its ID = 851.

At some point I figured out that my problem might be a timing issue indeed. Instead of using the SPSite.RootWeb reference I decided to create a new one using the SPSite.OpenWeb() method. All of a sudden the code above started working: while the 851 List Template wasn’t available in the RootWeb, it was right there on the glass after opening a new instance of SPWeb!

SharePoint 1 – 1 me

Lessons learned

While configuring all the different elements that participate in the provisioning process it’s very important that you also watch out for the timing problems. Since the instantiated objects cannot be refreshed it is important to check if those objects have been created after provisioning the configuration pieces you rely on, and if not to create a new instance yourself.

Technorati Tags: SharePoint 2010

Others found also helpful: