1
votes

I have a DataTable, and I want to add new items to a Sharepoint list using the data in the table's DataRows. But I'm having trouble adding data for a field where the type is "Person or Group", because this field seems to require an ID, not just "lastname, firstname". I made a class to build the CAML for a call to UpdateListItems(), which works fine for adding any other type of data to the list:

public class CAMLBuilder
{
    List<string> nameFields;

    public CAMLBuilder()
    {
        nameFields = new List<string>();
        nameFields.Add("Requestor");
    }

    public XmlElement batchAddElement(DataTable addTable)
    {
        XmlDocument doc = new XmlDocument();
        XmlElement element = doc.CreateElement("Batch");
        element.SetAttribute("OnError", "Continue");
        element.SetAttribute("ListVersion", "1");
        element.SetAttribute("ViewName", "");
        int methodCtr = 1;
        string batchStr = "";
        foreach (DataRow dr in addTable.Rows)
        {
            batchStr += "<Method ID='" + methodCtr + "' Cmd='New'>";
            foreach (DataColumn dc in addTable.Columns)
            {
                batchStr+="<Field Name='"+dc.ColumnName+"'>" + convertName(dc.ColumnName,Convert.ToString(dr[dc])) + "</Field>";
            }
            batchStr+="</Method>";
            methodCtr++;
        }
        element.InnerXml = batchStr;
        return element;
    }

    private string convertName(string columnName,string name)
    {
        if (nameFields.Contains(columnName))
        {
            name = "-1;#" + name;
        }
        return name;

    }

}

The "-1;#" in convertName() is something that I saw in this discussion as a workaround that lets you avoid looking up the person's ID. But it doesn't work; I get this error message in my returned XML:

0x81020054The user does not exist or is not unique.

Is there a way to build the CAML so that I don't need the ID and can just use the name?

1

1 Answers

0
votes

My solution so far is to use the People.asmx web service. The following code assumes that I have created a reference to the web service called PeopleService, and an instance of the service called ps:

public string findPersonID(string searchText)
        {
            PeopleService.PrincipalInfo[] arrayPrincipalInfo = ps.SearchPrincipals(searchText, 10, PeopleService.SPPrincipalType.All);
            if (arrayPrincipalInfo.Count() > 0)
            {
                return Convert.ToString(arrayPrincipalInfo[0].UserInfoID);
            }
            else
            {
                return string.Empty;
            }
        }

This is not ideal, because it requires that every row in my DataTable must call the web service separately (maybe optimized by grouping all identical names and only calling the function once for each unique name), which is a lot of web traffic if there are a lot of names. Hopefully someone else has a better solution.