1

I am developing a console application to extract data from a SharePoint 2013 server using the .NET client object model of the SharePoint Server 2013 Client Components SDK:

using (var clientContext = new ClientContext(SharePointUrl))
{
    var list = clientContext.Web.Lists.GetByTitle(listName);

    var camlQuery = CamlQuery.CreateAllItemsQuery();

    var listItems = list.GetItems(camlQuery);
    clientContext.Load(listItems, GetFields(fields));

    clientContext.ExecuteQuery();

    return listItems.ToList();
}

This is the GetFields() method I call to construct the list of fields I request:

private Expression<Func<ListItemCollection, object>>[] GetFields(IEnumerable<string> fields)
{
    return fields
        .Select(field => (Expression<Func<ListItemCollection, object>>)(items => items.Include(item => item[field])))
        .ToArray();
}

While looping through the results, I retrieve the value of a User-type field like this:

var employee = (FieldUserValue)listItem[fieldName];

There is one big list -- "Demands" -- that is giving me troubles for some User-type fields: whenever I even include these as a field that needs to be retrieved via the GetFields() method (see above), I get the infamous "Value does not fall within the expected range." error. For instance, "DTBusinessResponsible" can be retrieved, yet "DTSupplyLeadResponsible" cannot.

I have been told that "Demands" contains two ContentTypes: "Demand" and "I-Demand". The fields that are giving me issues are exclusive to "I-Demand".

I cannot figure out how I can retrieve these missing fields. I suppose I need to change the content type when I query the "Demands" list, but I'm not clear on how to do this.


UPDATE: I've tried retrieving the ContentTypes for "Demand" and "I-Demand" and adding them to list:

var demandContentType = clientContext.Web.ContentTypes.GetById(contentTypeByName["Demand"]);
var iDemandContentType = clientContext.Web.ContentTypes.GetById(contentTypeByName["I-Demand"]);

list.ContentTypesEnabled = true;
list.ContentTypes.AddExistingContentType(demandContentType);
list.ContentTypes.AddExistingContentType(iDemandContentType);

No use, I get an error telling me both ContentTypes are already present.


UPDATE: I've also asked this on StackOverflow.

0

I think you check for each item field ContentTypeID to get current content type and retrieve contextual field.

To get content type ID with name, you can call function like this

var listContentType = ctx.Web.Lists.GetByTitle(listTitle).ContentTypes.GetByName(listContentTypeName) and retrieve ID
  • The problem is I cannot even retrieve these fields. When I add them via clientContext.Load(listItems, GetFields(fields)); the query crashes. Both "Deamnds" and "I-Demand" are part of the ContentTypes of list. – BCdotWEB Sep 11 '15 at 10:10
0

Through much trial and error, I have managed to get this to work:

var fields = new List<string>
{
    "DTSupplyAccountable",
    "DTSupplyLeadResponsible",
    "Author",
    "Editor",
    "ID"
};

var viewXml = new StringBuilder();

viewXml.AppendLine("<ViewFields>");
foreach (var field in fields)
{
    viewXml.AppendFormat("<FieldRef Name=\"{0}\" />", field).AppendLine();
}
viewXml.AppendLine("</ViewFields>");

viewXml.AppendLine("<Query><Where><Eq><FieldRef Name=\"ContentType\" /><Value Type=\"Computed\">I-Demand</Value></Eq></Where></Query>");

var camlQuery = new CamlQuery {ViewXml = string.Format("<View Scope=\"RecursiveAll\">{0}</View>", viewXml)};

List<ListItem> results;

using (var clientContext = GetClientContext())
{
    var list = clientContext.Web.Lists.GetByTitle("Demands");
    var listItems = list.GetItems(camlQuery);
    clientContext.Load(listItems);
    clientContext.ExecuteQuery();
    results = listItems.ToList();
}

Here is the crucial detail (apart from the obvious <Where><Eq><FieldRef Name=\"ContentType\" /><Value Type=\"Computed\">I-Demand</Value></Eq></Where>):

ViewXml = string.Format("<View Scope=\"RecursiveAll\">{0}</View>", viewXml)

In fact, it's Scope=\"RecursiveAll\" that is the important part. I encountered it when looking with Fiddler to the various requests that were sent to the server and noticing that the working calls all included this:

<Property Name="ViewXml" Type="String">&lt;View Scope="RecursiveAll"&gt;&#xD;
    &lt;Query&gt;&#xD;
    &lt;/Query&gt;&#xD;
&lt;/View&gt;</Property>

On a whim I decided to add Scope="RecursiveAll" to my code, and it worked.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.