I am attempting to update metadata for documents in a document library (or List) using the client object model. I have whittled down a number of the error messages I was getting and now I am hitting a new problem:
A number of metadata fields in the content type for these items are lookup fields, and a number of those lookups are multi-select. Most of them are not required, however when I test the application I get errors from SharePoint telling me that "Metadata property [Sales Model Number] is required" which is just not true.
How do I put a blank value into a multi-select lookup field or otherwise avoid this error?
private void DoMetadataUpdateEx(DataRow row, ListItem item)
{
if (item.File != null || _sharePoint.CurrentList.ForceCheckout)
{
try
{
item.File.CheckOut();
_sharePoint.Context.ExecuteQuery();
}
catch (Exception) { }
}
foreach (MetaMap mm in _metaMapping)
{
if (mm.ForceUse)
{
//Field f = _sharePoint.CurrentList.Fields.GetByInternalNameOrTitle(mm.SharePointColumn);
Field f = _sharePoint.GetCurrentFieldByTitle(mm.SharePointColumn);
switch (f.FieldTypeKind)
{
case FieldType.MultiChoice:
string[] mcvals = row[mm.ExcelColumn].ToString().Split(',', ';');
item[f.InternalName] = mcvals;
break;
case FieldType.Lookup:
if((f as FieldLookup).AllowMultipleValues)
{
string[] mlvals = row[mm.ExcelColumn].ToString().Split(',', ';');
List<FieldLookupValue> newVals = new List<FieldLookupValue>();
FieldLookupValue[] oitemsalesmodelnum = (FieldLookupValue[])item[f.InternalName];
foreach (string ev in mlvals)
{
ListItem li = _sharePoint.GetLookupValue(f as FieldLookup, ev);
if (li == null)
{
continue;
}
FieldLookupValue flv = new FieldLookupValue();
flv.LookupId = li.Id;
newVals.Add(flv);
}
if (newVals.Count > 0)
{
item[f.InternalName] = newVals.ToArray<FieldLookupValue>();
}
else
{
newVals.Add(new FieldLookupValue());
item[f.InternalName] = newVals.ToArray<FieldLookupValue>();
}
}
else
{
ListItem li = _sharePoint.GetLookupValue(f as FieldLookup, row[mm.ExcelColumn].ToString());
if (li != null)
{
FieldLookupValue flv = new FieldLookupValue();
flv.LookupId = li.Id;
item[f.InternalName] = flv;
}
}
break;
case FieldType.Computed:
throw new NotImplementedException("Computed columns are not yet implemented");
case FieldType.Integer:
item[f.InternalName] = Int32.Parse(row[mm.ExcelColumn].ToString());
break;
default:
item[f.InternalName] = row[mm.ExcelColumn].ToString();
break;
}
}
}
item.Update();
//_sharePoint.Context.Load(item);
item.Context.ExecuteQuery();
if (item.File != null || _sharePoint.CurrentList.ForceCheckout)
{
try
{
item.File.CheckOut();
_sharePoint.Context.ExecuteQuery();
}
catch (Exception) // ignore checkout exception
{ }
item.File.CheckIn("Modified by SP2010 Excel List Updater", CheckinType.MajorCheckIn);
_sharePoint.Context.ExecuteQuery();
}
}// end DoMetadataUpdateEx()
* UPDATE *
SO, I made some changes, notably by adding the value that was missing from the lookup before to the lookup list, and got the same error. So, the field was being assigned a legitimate value now, and it still is throwing this "field is required" error. Not fun. I am of the impression perhaps there's something wrong with the field itself... Does anybody out there have thoughts? I'll probably poke around a little more then delete and recreate the field altogether.
* UPDATE 2 *
Doing some more debugging has led me to the following discovery: After the Update() and ExecuteQuery() calls, the item reverts back to its original metadata, so when I try to check it in it's applying invalid values, thus the error message. Now I'm really confused. Maybe I need to do the update and the checkin during the same ExecuteQuery() instead of trying to do the update first and then check in later?
Thanks,
- Matt
_sharePoint
object? It isn'tClientContext
?ClientContext
around as a parameter when it's needed, but all inside a using block... this is an interesting style.