5

I have a custom content type, and a custom list definition based on that content type.

I am adding two new fields to the content type in a feature upgrade. Adding the new fields to the content type and pushing that down to existing lists works just fine. However, the new fields end up with null values on existing list items, so I am trying to update all existing list items of my custom content type with some default values.

Here is my code from my feature upgrade custom action:

SPSite site = properties.Feature.Parent as SPSite;

SPContentTypeId myCTypeID = new SPContentTypeId("0x01-content-type-id-here");
SPContentType myContentType = site.RootWeb.ContentTypes[myCTypeID];

Guid choiceFieldId = site.RootWeb.Fields.GetFieldByInternalName("FieldOne").Id; // a choice field
Guid booleanFieldId = site.RootWeb.Fields.GetFieldByInternalName("FieldTwo").Id; // a boolean field

IList<SPContentTypeUsage> usages = SPContentTypeUsage.GetUsages(myContentType);
foreach(var usage in usages)
{
    if (usage.IsUrlToList)
    {
        using (SPWeb web = site.OpenWeb(usage.Url, false))
        {
            SPList myList = web.GetList(usage.Url);
            // loop through items by index instead of foreach to avoid the "collection was modified" error
            for (var i = 0; i < myList.ItemCount; i++)
            {
                myList.Items[i][choiceFieldId] = "Default Choice Value";
                myList.Items[i][booleanFieldId] = true;
                // there is an "ItemUpdated" event receiver that I would like to avoid running
                using (DisabledEventFiringScope scope = new DisabledEventFiringScope())
                {
                    // use SystemUpdate(false) to keep existing Modified, ModifiedBy and version values
                    myList.Items[i].SystemUpdate(false);
                }
            }
        }
    }
}

If I step through the code during the upgrade process, it seems to work, the right lists are found, and the right number of items are looped through, and the code throws no errors.

However, the values for those fields don't stick. If I go back in and look at those list items, the fields still have null values.

Why won't my updates stick?

3
  • did you try Web.Update() or AllowUnsafeUpdates = true? Commented Apr 26, 2017 at 18:53
  • No, but I'm not sure either one of them is relevant. Web.Update() will update the SPWeb object, and I need to update SPListItem objects. And AllowUnsafeUpdates is to allow updating of items in a GET request, but this is all getting triggered by calling SPFeature.Upgrade() from a Powershell script, so there is no HTTPContext involved. (Is there?) That all being said, I suppose it wouldn't hurt to try... Commented Apr 26, 2017 at 19:11
  • can you iterate over listitemcollection ? Somewhat like SPListItemCollection items = list.Items; foreach(SPListItem in items) and check ? Commented Apr 27, 2017 at 4:26

2 Answers 2

2

Interesting. It had to do with how I was accessing the SPListItem objects. I needed to explicitly get myList.Items[i] as an SPListItem.

Once I changed the inner part of the for loop to be

// loop through items by index instead of foreach to avoid the "collection was modified" error
for (var i = 0; i < myList.ItemCount; i++)
{
    SPListItem item = myList.Items[i];
    item[choiceFieldId] = "Default Choice Value";
    item[booleanFieldId] = true;
    // there is an "ItemUpdated" event receiver that I would like to avoid running
    using (DisabledEventFiringScope scope = new DisabledEventFiringScope())
    {
        // use SystemUpdate(false) to keep existing Modified, ModifiedBy and version values
        item.SystemUpdate(false);
    }
}

then the updates stuck as expected.

1
  • Very strange. Your solution worked for me too. Anyone with extra time to elaborate why is this happening? Commented Mar 20, 2018 at 7:55
1

As a follow-up as to why the change was necessary, each time you access myList.Items[i] you're getting a new reference. You need to reference the item in a variable as you did in your solution to be able to change multiple fields and then call Update (or SystemUpdate) on that same object with the changes.

I would have put this as a comment on that answer, but I don't have the reputation yet.

1
  • Huh. Interesting. I see exactly what you're saying. Commented Aug 11, 2022 at 14:33

Your Answer

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

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