Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I have a quite complex application that is split into several features.

In order to hide this complexity, I set the IsHidden property of the feature to true, then have created a "master" feature. This feature have a custom feature receiver which purpose is to chain properly the activation of the hidden features.

I use this code :

    // Order matters !
    private static readonly IEnumerable<Guid> g_SiteFeatures = new string[] {
            "8a190c52-37e2-4dc9-bd7d-10a1aa3574eb" // Feat1
        }.Select(idStr => new Guid(idStr));


    // Order matters !
    private static readonly IEnumerable<Guid> g_WebFeatures = new string[] {
            "b004f353-38f9-46d4-bd15-20644aa525c5", // Feat2
            "fde2b1cc-51e1-4654-b754-addcb571ce12" // Feat3                
        }.Select(idStr => new Guid(idStr));

    private void ActivateHiddenFeatures(SPSite site, SPWeb web)
    {
        foreach (var siteFeature in g_SiteFeatures)
        {
            if (site.Features.All(f => f.DefinitionId != siteFeature)) // Avoid to fail with  already activated features
            {
                site.Features.Add(siteFeature);
            }
        }
        foreach (var webFeature in g_WebFeatures)
        {
            if (web.Features.All(f => f.DefinitionId != webFeature)) // Avoid to fail with  already activated features
            {
                web.Features.Add(webFeature);
            }
        }
    }

This code works, but I'm experiencing randomly failures in this code. Especially, I have failures stating that some list does not exists. However, this lists is created by one the hidden features.

If I let visual studio activate the feature in place of my master feature, everything works fine.

If I attach a debugger to the receiver of the master feature, and I "wait" a bit, the code runs correctly.

All this evidence let me think that the Add method of the site.Features and web.Features are not synchronous, but asynchronous. However, nothing in the documentation is stating something like this.

FYI, the code that fails is an event receiver that intercept ItemAdded events on one of the list I created in one the hidden feature. Just after activating the features, I inject some data :

    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
        System.Diagnostics.Debugger.Break();
        properties.RunContextualized((web, site) => // Utility method that extract web and site from properties
        {
            ActivateHiddenFeatures(site, web);
            LoadInitialData(web, site);
        });
    }

    private void LoadInitialData(SPWeb web, SPSite site)
    {
        // Insert some data in on the list created from a hidden feature
        // the insertion is made using a SPMetal generated context
    }

I'm quite stuck with these situation, as I experience an unexpected behavior.

I no solution is found, I'll end-up by writing a custom timer job to inject the data later, but it will lead to other functional issues.

share|improve this question
add comment

1 Answer 1

up vote 1 down vote accepted

Since you are hiding the other features, this is a candidate ripe for Activation Dependencies (the hidden ones will auto-activate during the activation of the visible master feature)

This would help you avoid having to write the above code.

Visual Studio has an interface for specifying this (I know I'm likely telling you things you already know) but.. if you're not using Vis. Studio, the master feature ends up looking like this:

<Feature xmlns="http://schemas.microsoft.com/sharepoint/" Title="MyCompany - Create Log" Creator="bkwdesign" Description="Creates a new instance of a MyCompany log list, based on a custom list definition" Id="0ef865dd-8171-4dc7-a2e5-f80e5488a3AA" ImageUrl="MyCompany/MyCompanyFeatureIcon.png" ImageUrlAltText="Creates an instance of a list for MyCompany comments and signatures" ReceiverAssembly="MyCompany, Version=1.0.0.5, Culture=neutral, PublicKeyToken=130eeb2d789a2e4b" ReceiverClass="MyCompany.MyCompany_LogInstanceEventReceiver" Scope="Web" Version="0.0.0.1">
  <ActivationDependencies>
<ActivationDependency FeatureDescription="Defines common columns for MyCompany decision lists." FeatureId="d0e39492-9999-4d3f-9999-c1f8e457e001" FeatureTitle="MyCompany Site Columns" />
    <ActivationDependency FeatureDescription="Defines content types needed in MyCompany decision lists." FeatureId="d0e39492-9999-4d3f-9999-c1f8e457e002" FeatureTitle="MyCompany Content Types" />
  </ActivationDependencies>
  <ElementManifests>
    <ElementManifest Location="eSWRCCommentsList\Elements.xml" />
    <ElementFile Location.... blah blah
    ....
  </ElementManifests>
</Feature>

FYI - here's another post that seems to indicate that feature dependencies execute synchronously in-order: http://social.msdn.microsoft.com/Forums/eu/sharepointdevelopment/thread/9f17b9a7-13d6-4d5b-9566-b9ca66df20ea

My experience with the above has been very positive.

share|improve this answer
    
While this can be a valid solution to solve my problem, it does not actually answer to my question. What about if I have to do this in code (for whatever reason) ? –  Steve B Jun 19 '12 at 7:31
1  
And unfortunately, this technique cannot mix different scope. My features have dependencies on site and web features. Unless I create two "main" features, this won't work (and I loose the one click to enable). –  Steve B Jun 19 '12 at 7:37
    
I split into two main features, one for site scoped dependencies, the other with web scoped dependencies. I use pure xml sub activation. The problem still persists. My main features receiver cannot find list created by a feature dependency. Is the event receiver of a feature fired after the dependencies activation ? –  Steve B Jun 19 '12 at 8:02
1  
Finally, I solved my problem by combining both feature dependencies and custom code to populate data. If the features are activated by the feature dependencies the list is actually available in the master feature receiver. If the feature is actived by the master receiver just before the data is injected, the list is not available. I'm still feeling the FeaturesCollection.Add is not synchronous. I'll try on MSDN forum to see if someone can explain. –  Steve B Jun 19 '12 at 9:46
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.