3

I have a tool to update all items in SP (link replacement). The tool works most of the time but sometimes it throws me an ArgumentException ("Value does not fall within the expected range.").

Here is the code how I iterate and try to access the value:

   foreach (SPList list in web.Lists)
   {
         foreach (SPListItem item in list.Items)
         {
              foreach (SPField field in list.Fields)
              {
                   if (!field.ReadOnlyField)
                   {
                       if (item.Fields.Contains(field.Id) && item[field.Id] != null)
                       {

The exception is thrown at item[field.Id] and I don't see why. The field is clearly in the item fields collection as the item.Fields.Contains(field.Id) returns true. Also of course the field.Id is a normal Guid.

Am I making some logical error here?

7
  • 1
    I now see the possible source of the problem. The SPListItem contains 86 fields ("Field" property) but there are seem to be only 83 values (value of the item.ListItems.NumberOfFields Property). Strangely the property "item.ListItems.Count" has a value of "4". Anyone an idea why there is a difference of 3 and how to get the 3 "missing" values?
    – Shihan
    Commented Jul 11, 2011 at 12:13
  • Have you (or anyone else) by any chance added the missing fields programmatically, and not called SPField.Update?
    – Stu Pegg
    Commented Jul 12, 2011 at 7:42
  • I don't know but I dont think that is the case. The site is pretty 0815 and out-of-the-box. It's a site of a customer that we migrated from SP2007 to 2010. Is there a way to check if that is the case?
    – Shihan
    Commented Jul 12, 2011 at 7:56
  • Figure out which fields are missing, then update them through the UI or programmatically. If this is the source of the issue, your problems should then magically disappear.
    – Stu Pegg
    Commented Jul 12, 2011 at 8:25
  • I tried to update them programmatically but it failed as it said it had a save conflict (changes by a different user).
    – Shihan
    Commented Jul 12, 2011 at 14:54

7 Answers 7

5
+50

I've had success by not using .ID, but using InternalName with .ContainsFieldWithStaticName(). I also check Hidden and CanBeDeleted on the field as these are more system fields and not custom ones, so I'm not worried about them.

Sample below

SPWeb web = SPContext.Current.Web;
foreach (SPList list in web.Lists)
{
    foreach (SPListItem item in list.Items)
    {
        foreach (SPField field in item.Fields)
        {
           if(!field.Hidden && !field.CanBeDeleted && item.Fields.ContainsFieldWithStaticName(field.StaticName) && item.GetFormattedValue(field.InternalName) != null)
            {
                //CODE HERE
            }                        
        }
1
  • Your solution is the only one that really helped (in my case here). I had to alter the "if" a little and add "&& item[field.Id] != null" at the and additionally but now it works like desired. Thx!
    – Shihan
    Commented Jul 14, 2011 at 9:45
2

I recently had this problem myself; the only difference being that I was using a CAML query. If your code above is abridged and you were too, this may be of use to you.

The problem boiled down to two issues:

a) I hadn't added one of the columns to the ViewFields XML, so the field wasn't in the SPListItem at all.

b) Once I did add it, I had to set my new favourite undocumented attribute Nullable:

<FieldRef Name="Notes" Nullable="True"/>

This ensures there's a null entry for empty fields (as opposed to no entry), so item["Note"] won't return a NullReferenceException immediately; allowing item["Note"] != null.

1

its difficult to say why you're getting the exception (some casting issue somewhere) , but i've reworked two lines of your code which might help:

  1. Instead of iterating through all fields in the List, Iterate through all fields in the List item

  2. Indexers is a Exception nightmare in c#, try to use a method which should always return something and not throw exceptions (that's the theory anyways).

Here we go:

    SPWeb web = SPContext.Current.Web;
    foreach (SPList list in web.Lists)
    {
        foreach (SPListItem item in list.Items)
        {
            foreach (SPField field in item.Fields)
            {
                if (item.Fields.Contains(field.Id) && item.GetFormattedValue(field.InternalName) != null)
                {
                    //CODE HERE
                }                        
            }
5
  • I tried your code but unfortunately it doesn't solve my problem. The exception still occurs. Also I don't find a suitable method to get the field value. (Un)funny thing is, when I try the approach of this page: jeremysublett.com/archive/2009/08/01/… I am able to retrieve the values of to more items than before but on the next item it crashes again. And I really don't see WHY I should use the approach with SPQuery but maybe someone can enlighten me.
    – Shihan
    Commented Jul 8, 2011 at 15:59
  • Which field does it break on? Stick a debugger in and let it run til the exception throws.
    – James Love
    Commented Jul 8, 2011 at 17:39
  • Have you ever tried to check item.ID ?
    – Fox
    Commented Jul 12, 2011 at 7:37
  • In other words, if(!string.isnullorempty(item.ID) ?
    – Fox
    Commented Jul 12, 2011 at 7:37
  • I believe you mean the "field.Id". But anyway, the ID is there (and a valid GUID, it isn't a string).
    – Shihan
    Commented Jul 12, 2011 at 11:42
1

I found a solution to the original problem that was posted here, it took me whole day struggling with xml returned by query. Solution is, In ViewFields, terminate the internal name up to 32 charachters. And then, while getting value, use the internal name terminated up to 32 chars.

This is definately poorly tested code by Microsoft pushed in SP 2010. They must do a better job testing it.

Any fields, which have internal name greater than 32 are a problem if you use viewfields. If you don's use viewfields, you are good, there's no issue.

0

Try to set the Resource Throttling value up for "List View Lookup Threshold". Go to the Central Admin > Application Management > Manage web applications. Select the web application that needs to be changed, and then go to General Settings > Resource Throttling.

Important note: always evaluate the impact of changing default threshold values in SharePoint and always be aware of the amount of columns in your Lists.

Cheers

1
  • I already did increase this value (as some sites suggested it). But it made no difference.
    – Shihan
    Commented Jul 11, 2011 at 6:45
0

I seem to remember running across this one too. Interestingly, GUID isn't the most reliable means of getting the value from an item; using InternalName or title is much more predictable.

If you use a string indexer it'll check that string against Title, InternalName, and the static name for a match.

SPListItem.Item Property (String)

Why doesn't GUID work all the time? Microsoft knows; but they're not telling.

Edit: Looking at my commit notes, it looks like I switched from ID to InternalName to improve 2007 reliability. So this may or may not help with 2010.

1
  • No change, even when using a string indexer.
    – Shihan
    Commented Jul 11, 2011 at 11:59
0

First of all:

replace your line of code

foreach (SPListItem item in list.Items) 

with

SPListItemCollection items = l.Items;
foreach(SPListItem item in items)

that's a best practice. Try to replace your line of code that bugs out with:

if (item.Fields.Contains(field.Id) && item.Fields[field.Id] != null)

I'm not sure, but it's possible that in the item[] indexer, only fields exist that contain a value, while the possible fields are in the item.Fields. This explains why item.Fields contains(id) returns a value and item.Fields[id] returns an ArgumentException

1
  • Thank you for the best practice advide. The part with the field however does not work as I don't want to get the value of the field but the item value for a field.
    – Shihan
    Commented Jul 14, 2011 at 9:42

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.