SharePoint SPListItem quirks
There are some funny things going on inside SharePoint, and this is one of the funniest…
We have a list, with two fields:
<Field Type="Text" DisplayName="Category" MaxLength="255" Name="Category0" ColName="nvarchar17" /> <Field Name="Category" FromBaseType="TRUE" Type="Choice" DisplayName="Category (deprecated)" Format="Dropdown" FillInChoice="FALSE" ColName="nvarchar2" ><!-- CHOICES --></Field>
Note that one has the DisplayName of ‘Category’ and the other has the Name of ‘Category’.
The one with the Name ‘Category’ is deprecated, and we actually want to populate the field with the DisplayName ‘Category’.
You’d expect this would be fine… so consider that we have an empty list and that we create a new item and try and populate the item:
SPListItem newListItem = spList.Items.Add(); newListItem["Title"] = "The title"; newListItem["Category"] = "Category 1"; newListItem.Update();
That should work right? I mean MSDN very plainly states that on a SPListItem that you access a field using the DisplayName of the SPField that you want to set the value against.
It tries to populate the wrong field.
Why? Because it seems that if a SPField exists that has an InternalName the same as a DisplayName, then that SPField takes priority. As the Name property of a SPField *is* the InternalName, we’ve actually just attempted to assign the string “Category 1″ to the Choice Field that is “Category (deprecated)”.
A very subtle but pain in the arse thing that.
So how to get around it? Well, instead of passing in the DisplayName you can use the overloaded version of spListItem[] to pass in the int32 index of the SPField in the spList.Fields collection.
So if you loop the spList.Fields collection, work out where the real “Category” field is that we want to update, and grab the index… you’d expect to be able to update the list item right?
Right, but… not if the item you are creating is the first item to ever go into the list. It will work for every subsequent item, but never the first item.
For some reason the index based accessors only work after an item exists, so if we go back to that original piece of code and update it with the Field index:
SPListItem newListItem = spList.Items.Add(); newListItem["Title"] = "The title"; newListItem[2] = "Category 1"; newListItem.Update();
That won’t work.
Instead you have to save the item, and then grab a fresh instance of the item and save that:
SPListItem newListItem = spList.Items.Add(); newListItem["Title"] = "The title"; newListItem.Update(); SPListItem existingListItem = spList.GetItemByID(newListItem.ID); existingListItem[2] = "Category 1"; existingListItem.Update();
And that piece of code works.
The rules here:
- You can’t set a value to a field using the DisplayName if another field exists with a matching Name / InternalName.
- You can’t use the index based accessors until an item exists within the SharePoint list.
This probably won’t matter to the majority of SharePoint developers, but to those who encounter either of the above, it’s really worth noting them down… close to three days we lost on this.
Credit to Louise B for discovering through much pain the first part of this two-part bug.
8 Comments, Comment or Ping
Evets
thank you for those examples, it helps me a lot :)
Mar 8th, 2007
daz
it helped a lot!
si’ si’ …
Apr 3rd, 2007
Eddy
Thanks for this.
It is a disgrace that it is not documented in MSDN.
Apr 6th, 2007
sudhakar
really helped me, good job, thanks
Jul 12th, 2007
Joel Corra
You could probably turn this into a whole site dedicated to SharePoint quirks. For instance, one I came across recently is that if you update an SPListItem through the object model, and it has a Notes/Comments field with versioning enabled (one of the default fields on a Contact list), it blanks out the Notes field–if you check the version history, it actually shows Notes being set with a blank value. The original notes then no longer show in any Data Sheet view. However, that doesn’t happen if you update the item through the regular SharePoint interface.
Bil Simser has also documented at least 2 “quirks” with the AddFieldAsXml method of the SPList:
AddFieldAsXml cannot be used to set the InternalName correctly
http://weblogs.asp.net/bsimser/archive/2005/07/21/420147.aspx
SharePoint basically ignores the InternalName property in the XML definition and uses the DisplayName for the both the internal name and display name.
AddFieldAsXml… I wish this monkey would go away
http://weblogs.asp.net/bsimser/archive/2005/07/27/420766.aspx
The properties of the node in the XML definition have to be in a certain order, or it throws an error.
Mar 25th, 2008
kipper stiever
dude, what a PIA! i just ran into the same issue. thanks for the post, this would have taken me 3 days to figure out as well, no doubt.
May 8th, 2008
Erik Burger
Got to love those “quirks” eh? Excellent post, really useful.
Does anyone have any deas on how we can prevent ourselves and our fellow devs from running into this problem? Use the InternalName attribute? I doubt that would make a difference but maybe I’m missing something. Use an extension method? And how would it look?
It would be interesting to know why MS doesn’t provide a way to get a Field by its InternalName. I’ve run into a major problem using an MS template that references a Field by its DisplayName (details here: http://www.reversealchemy.net/2008/09/10/sharepoint-custom-templates-and-language-packs/). Why not use the InternalName? Wouldn’t that make life easier?
Or am I *really* missing something?
Cheers,
Erik
Oct 22nd, 2008
Reply to “SharePoint SPListItem quirks”