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 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?

share|improve this question
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 Jul 11 '11 at 12:13
    
Have you (or anyone else) by any chance added the missing fields programmatically, and not called SPField.Update? –  Stuart Pegg Jul 12 '11 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 Jul 12 '11 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. –  Stuart Pegg Jul 12 '11 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 Jul 12 '11 at 14:54

6 Answers 6

up vote 4 down vote accepted
+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
            }                        
        }
share|improve this answer
    
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 Jul 14 '11 at 9:45

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.

share|improve this answer

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
                }                        
            }
share|improve this answer
    
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 Jul 8 '11 at 15:59
    
Which field does it break on? Stick a debugger in and let it run til the exception throws. –  James Love Jul 8 '11 at 17:39
    
Have you ever tried to check item.ID ? –  Fox Jul 12 '11 at 7:37
    
In other words, if(!string.isnullorempty(item.ID) ? –  Fox Jul 12 '11 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 Jul 12 '11 at 11:42

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

share|improve this answer
    
I already did increase this value (as some sites suggested it). But it made no difference. –  Shihan Jul 11 '11 at 6:45

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.

share|improve this answer
    
No change, even when using a string indexer. –  Shihan Jul 11 '11 at 11:59

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

share|improve this answer
    
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 Jul 14 '11 at 9:42

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.