2

I am trying to create a SharePoint list based on a list template via a feature. The code for creating the list is in the FeatureActivated event handler of the feature's EventReceiver.cs file. The list template has been added to a Module within the project.

The list is created as expected when the feature is activated via site collection features page. The problem arises when the Enable-SPFeature command is used. This command activates the feature, and adds the list template to the list template gallery as expected. But the list is not created.

My guess is that when the PS command is issued, the code to create the list gets executed before the template is placed in the template gallery. This results in list not being created because, it cannot find the template. The ULS viewer logs the following message when using the PowerShell: "Value does not fall within the expected range." With UI activation, there is no such log. (Update 2: The list was not created even when the template was already present in the gallery. So, timing does not seem to be the issue.)

In my case, the featuer is hidden; I don't have an option of activating it via the UI. So, I would like to know the difference, if any, in the sequence of events that takes place when feature is activated via PS or UI.

UPDATE 1 First part of my EventReceiver code, where the lists are created.

// Site collection where the feature is deployed           
SPSite site = properties.Feature.Parent as SPSite;
Constants.SiteCollectionUrl = site.RootWeb.Url;

try
{
     // Create Configuration List, if it does not exist
     string configListTitle = Constants.ConfigListTitle;
     string configListDescription = Constants.ConfigListDescription;
     string configListTemplateTitle = Constants.ConfigListTemplateTitle;

     PhotoImportHelper.TryCreateList(configListTitle, configListDescription, configListTemplateTitle);
     PhotoImportHelper.TryAddDefaultConfigValues(PhotoImportHelper.GetConfigList(site, configListTitle), Constants.GetDefaultConfigKeyValuePairs());

     // Create Report List, if it does not exist
     string reportListTitle = Constants.ReportListTitle;
     string reportListDescription = Constants.ReportListDescription;
     string reportListTemplateTitle = Constants.ReportListTemplateTitle;

     PhotoImportHelper.TryCreateList(reportListTitle, reportListDescription, reportListTemplateTitle);

     // Create Exceptions list, if it does not exist
     string photoImportExceptionsTitle = Constants.PhotoImportExceptionsTitle;
     string photoImportExceptionsDescription = Constants.PhotoImportExceptionsDescription;
     string photoImportExceptionsTemplateTitle = Constants.PhotoImportExceptionsTemplateTitle;

     PhotoImportHelper.TryCreateList(photoImportExceptionsTitle, photoImportExceptionsDescription, photoImportExceptionsTemplateTitle);
}
catch (Exception e)
{
     SPDiagnosticsService.Local.WriteTrace(0, new SPDiagnosticsCategory(Constants.TimerJobTitle, TraceSeverity.Unexpected, EventSeverity.Error), TraceSeverity.Unexpected, e.Message, e.StackTrace);
}

UPDATE 3: Helper class code

/// <summary>
/// Creates a list given the list title, description, template to use, and enables versioning.
/// </summary>
/// <param name="listTitle">String Value of the title of the list to be created</param>
/// <param name="listDescription">String value of the description for the list being created</param>
/// <param name="listTemplateTitle">String value of the title of the list template to be used in list creation</param>
/// <param name="enableVersioning">Bool value that specifies whether or not to enable versioning on the list</param>
public static void TryCreateList(string listTitle, string listDescription, string listTemplateTitle, bool enableVersioning)
{
    using (SPSite site = new SPSite(Constants.SiteCollectionUrl))
    {
        SPList list = site.RootWeb.Lists.TryGetList(listTitle);
        if (list == null)
        {
            // Create list 
            Guid listGuid = site.RootWeb.Lists.Add(listTitle, listDescription, site.GetCustomListTemplates(site.RootWeb)[listTemplateTitle]);
            list = site.RootWeb.Lists[listGuid];
            site.RootWeb.Update();
        }

        // Turn on versioning
        list.EnableVersioning = enableVersioning;
        list.Update();
    }
}

UPDATE 4 The cause behind all this.

I had updated a "Constant" value (PhotoImportExceptionsTemplateTitle) in my helper file earlier today. For some reason, when issuing Enable-SPFeature command from PS, the old value persisted - which means, the old template name was being passed to the helper function that creates the list. I am still not sure why the old value persisted when issuing the command from PS.

2 Answers 2

2

I would suggest that you break the whole thing into two features, first one to deploy the List Template and second one to create the instance of the list based on template..

On the later one, you will need to define Feature Activation Dependency of List Template feature..

Both features can be hidden and you just need to activate the Feature that creates the List Instance.. It will make sure to activate the Template Feature by itself..

How to: Add and Remove Feature Dependencies

UPDATE

Actually I missed something, Hidden features can't have Activation Dependencies..

What I can think of still splitting this into two features but on Feature Activation event receiver, activate the List Template feature through code..

var featureGuid = new Guid("[Feature-GUID-Here]");
if (web.Features[featureGuid] == null) 
{
    web.Features.Add(featureGuid);
}
2
  • Hello Arsalan, Thank you for your answer. This workaround did cross my mind after reading this related question: sharepoint.stackexchange.com/q/38826/3995. The question still remains, however, if the two different ways of activating a feature do things differently; and, if yes, how?
    – GMalla
    Apr 11, 2014 at 18:54
  • Not sure what's happening at the back.. Apr 11, 2014 at 19:00
2

Make sure to not use SPContext.Current in the FeatureReciever, this will be NULL in powershell (due to lack of HttpContext basically).

This is one of the most common cause of errors in FeatureReceivers

8
  • Thanks Robert. It doesn't seem like I am using SPContext.Current in my FeatureReciever. I do use properties.Feature.Parent to get the SPSite. I don't believe that would be a problem during activation via PS, would it?
    – GMalla
    Apr 11, 2014 at 19:11
  • No that particular line should be fine, care to post your feature receiver code? Apr 11, 2014 at 19:15
  • +1 for this. I was just working with a jr. developer yesterday who said his WF worked when a user invoked it by performing an action but it was launched via code it threw NullRef exception. First thing I asked was, "Are you using SPContext?" Apr 11, 2014 at 19:27
  • @RobertKaucher, I think we all have been there. Just the other day I found SPContext in an event receiver that has been in production for 5 years. No one ever noticed Apr 11, 2014 at 19:33
  • @RobertLindgren Updated question with the code snippet. This is the first part of the code just upto where the list is created. Pretty straight forward simple code. The issue is with creating the "exception list." Didn't want to dump all the code here.
    – GMalla
    Apr 11, 2014 at 19:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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