5

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
7
  • Apparently this is a really good question! One upvote and no potential answers or other comments, yet.
    – Matt
    Commented Oct 26, 2012 at 0:40
  • thoughts in Update 2 did not really pan out.
    – Matt
    Commented Oct 26, 2012 at 17:48
  • What is this _sharePoint object? It isn't ClientContext? Commented Oct 26, 2012 at 19:00
  • it's a worker object that has a context attached so I can use the same context throughout my application. It also has some methods to help clean up some of the more verbose activities involved in manipulating the client object model.
    – Matt
    Commented Oct 26, 2012 at 20:06
  • Hmm, I always just pass my ClientContext around as a parameter when it's needed, but all inside a using block... this is an interesting style. Commented Oct 26, 2012 at 20:15

1 Answer 1

5

OK, SO I think I solved my problem. I actually had two things going on here:

1) A WCF connection propagates metadata updates on check-in to another web application (ASP.NET). The field I was constantly getting messages about IS required on that site. Wouldn't expect anyone on here to figure that out. I made the field required in SharePoint and set some default, bogus values so I could test the updating of my application.

2) After I fixed that issue, I noticed things were finally starting to check in, but none (well, ONE) of the fields were getting updated. I toyed around with it a little more and found that if I did an Update() call every time I looped through the fields it would, indeed, update them in SharePoint, too. It looks like the call to Update() was previously only updating the last metadata field to be set, or something like that.

New Code:

    private void DoMetadataUpdateEx(DataRow row, ListItem item)
    {
        ListItem updateItem = item;

        if (item.File != null || _sharePoint.CurrentList.ForceCheckout)
        {
            updateItem = item.File.ListItemAllFields;
            _sharePoint.Context.Load(updateItem);
            _sharePoint.Context.ExecuteQuery();
            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(',', ';');
                        updateItem[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)
                            {
                                updateItem[f.InternalName] = newVals.ToArray<FieldLookupValue>();
                            }
                            else
                            {
                                newVals.Add(new FieldLookupValue());
                                updateItem[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;
                                updateItem[f.InternalName] = flv;
                            }
                        }
                        break;
                    case FieldType.Computed:
                        throw new NotImplementedException("Computed columns are not yet implemented");
                    case FieldType.Integer:
                        updateItem[f.InternalName] = Int32.Parse(row[mm.ExcelColumn].ToString());
                        break;
                    default:
                        updateItem[f.InternalName] = row[mm.ExcelColumn].ToString();
                        break;

                }
            }
            updateItem.Update();
        }

        //updateItem.Update();

        if (item.File != null || _sharePoint.CurrentList.ForceCheckout)
        {
            item.File.CheckIn("Modified by SP2010 Excel List Updater", CheckinType.MajorCheckIn);
        }
        else
        {
            _sharePoint.Context.ExecuteQuery();
        }
    }// end DoMetadataUpdateEx()

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.