Can you help me getting the items of a SharePoint library (it is a library with document sets) using CSOM.
The library has a lot more than 5000 items and I know SharePoint has a limit of 5000, so I am trying to get them in batches of 500. Is it possible?
clientContext.Credentials = new SharePointOnlineCredentials(username, securePassword);
List oList = clientContext.Web.Lists.GetByTitle(libraryName);
clientContext.Load(oList);
clientContext.ExecuteQuery();
CamlQuery query = new CamlQuery();
query.ViewXml = "<View><RowLimit>500</RowLimit></View>";
ListItemCollection allDocumentSet = oList.GetItems(query);
clientContext.Load(allDocumentSet);
clientContext.ExecuteQuery();
I do not know why is not working. I get the following error.
Microsoft.SharePoint.Client.ServerException: 'The attempted operation is prohibited because it exceeds the list view threshold enforced by the administrator.'
Why do I get the error if I am getting only 500 items per batch?
Also, one additional question. When should I use "ExecuteQuery" and Load function?
Thanks!
You need run ExecuteQuery to retrieve/update the data from server.
Here is my sample test code to retrieve items more than 5000.
List lmsList = clientContext.Web.Lists.GetByTitle("LargeList");
ListItemCollectionPosition itemPosition = null;
while (true)
{
CamlQuery camlQuery = new CamlQuery();
camlQuery.ListItemCollectionPosition = itemPosition;
camlQuery.ViewXml = #"<View><RowLimit>500</RowLimit></View>";
ListItemCollection listItems = lmsList.GetItems(camlQuery);
clientContext.Load(listItems);
clientContext.ExecuteQuery();
itemPosition = listItems.ListItemCollectionPosition;
Console.WriteLine(itemPosition);
//foreach (ListItem listItem in listItems)
// Console.WriteLine("Item Title: {0}", listItem["Title"]);
if (itemPosition == null)
break;
Console.WriteLine(itemPosition.PagingInfo);
}
Related
I am trying to get a list of items from a specific view. Below is the code
Microsoft.SharePoint.Client.List _lists = context.Web.Lists.GetByTitle("Invoice Register");
context.Load(_lists);
context.ExecuteQuery();
int listCount = _lists.ItemCount; // i get 49000+ count here
View _listsView = _lists.Views.GetByTitle("IT Testing");
context.Load(_listsView);
context.ExecuteQuery();
CamlQuery _query = new CamlQuery();
_query.ViewXml = _listsView.ViewQuery;
Microsoft.SharePoint.Client.ListItemCollection items = _lists.GetItems(_query);
context.Load(items);
context.ExecuteQuery();
int _viewCount = items.Count; // I get nothing here.
The error I get is The attempted operation is prohibited because it exceeds the list view threshold enforced by the administrator
I have created indexes already
I have set the limit for "IT Testing" to 5000 as seen here.
If someone can guide, it would be helpful. I have gone through all the links I could.
Regards
#Ather Siddiqui,
there is no direct way to get items under a view as the view only has query schema and does not have any items. The caml query may get the same items that are under the view, but it will trigger the list view threshold.
#user2250152 has provided a good method, it's possible to get over 5000 items through Pagination. If you want to use the view query, you could change the query as below:
List tList = context.Web.Lists.GetByTitle("My test list");
CamlQuery camlQuery = new CamlQuery
{
ViewXml = #"<View><Query><Where><Gt><FieldRef Name='ID' /><Value Type='Counter'>20</Value></Gt></Where></Query><OrderBy><FieldRef Name ='FileLeafRef' /></OrderBy><RowLimit>4990</RowLimit></View>" // your view query
};
var itemColl = new List<ListItem>();
do
{
ListItemCollection listItemCollection = tList.GetItems(camlQuery);
context.Load(listItemCollection);
context.ExecuteQuery();
//
itemColl.AddRange(listItemCollection);
camlQuery.ListItemCollectionPosition = listItemCollection.ListItemCollectionPosition;
} while (itemColl.Count < 999); //view row limit
Console.WriteLine(itemColl);
I'm using this code to load a lot of items.
var itemsPerPage = 100;
var query = CamlQuery.CreateAllItemsQuery(itemsPerPage);
var loadMoreItems = false;
do
{
var items = list.GetItems(query);
ctx.Load(items);
ctx.ExecuteQuery();
loadMoreItems = items.Count == itemsPerPage;
query.ListItemCollectionPosition = items.ListItemCollectionPosition;
}
while (loadMoreItems);
It's based on this
CalmQuery.CreateAllItemsQuery
I have a list called "Books" with columns 'Name','AuthorName','ISBN' with type as text. Now I have another list called "BillTokenStore" and i want to add lookup column 'AuthorName' in "BillTokenStore". Below is what i have done.
using (ClientContext context = new ClientContext(webFullUrl: siteUrl))
{
context.Credentials = new SharePointOnlineCredentials(userName, GetPassWord());
Web web = context.Web;
ListCollection listCollection = web.Lists;
List list = listCollection.GetByTitle("BillTokenStore");
string schemaLookupField = #"<Field Type='Lookup' Name='InStock' StaticName='InStock' DisplayName='InStock' List = 'Books' ShowField = 'Title' /> ";
Field lookupField = list.Fields.AddFieldAsXml(schemaLookupField, true, AddFieldOptions.DefaultValue);
context.ExecuteQuery();
}
When i run this code, i am getting the error "value does not fall within the expected range sharepoint 2013". What is wrong here? Thanks in Advance.
Note: I am able to achieve the same thing thorough UI. I am also able to add other type of fields like choice,boolean and all through code.
You need to explicitly load the list and the fields of that list.
Also, we need to pass the GUID of the lookup column list.
Please try the below modified code:
using (ClientContext context = new ClientContext(webFullUrl: siteUrl))
{
context.Credentials = new SharePointOnlineCredentials(userName, GetPassWord());
Web web = context.Web;
List booksList = context.Web.Lists.GetByTitle("Books");
List list = context.Web.Lists.GetByTitle("BillTokenStore");
context.Load(list, l => l.Fields);
context.Load(booksList, b => b.Id);
context.ExecuteQuery();
string schemaLookupField = #"<Field Type='Lookup' Name='InStock' StaticName='InStock' DisplayName='InStock' List='"+ booksList.Id +"' ShowField = 'Title' />";
Field lookupField = list.Fields.AddFieldAsXml(schemaLookupField, true, AddFieldOptions.DefaultValue);
lookupField.Update();
context.Load(lookupField);
context.ExecuteQuery();
}
I have a custom sharepoint list called VSList, from which I can retrieve all items (4 columns altogether) using the following code:
string siteUrl = url2;
ClientContext clientContext = new ClientContext(siteUrl);
SP.List oList = clientContext.Web.Lists.GetByTitle("VSList");
CamlQuery camlQuery = new CamlQuery();
ListItemCollection collListItem = oList.GetItems(camlQuery);
clientContext.Load(collListItem, items => items.Include(item => item["Title"], item => item["qf2a"], item => item["_x0077_830"], item => item["u6zl"]));
clientContext.ExecuteQuery();
Is there any way to reverse it somehow, so I can upload data, and not download it?
Thanks in advance.!
This is fairly simple to do with the following code (edited my code to fit your list).
// Open client context to the site
var clientContext = new ClientContext(siteUrl);
// Use client context to open the list
var oList = clientContext.Web.Lists.GetByTitle("VSList");
var listCreationinformation = new ListItemCreationInformation();
var oListItem = oList.AddItem(listCreationinformation);
// Push information to individual tables in the selected list
oListItem["Title"] = value1;
oListItem["qf2a"] = value2;
oListItem["_x0077_830"] = value3;
oListItem["u6zl"] = value4;
oListItem.Update();
clientContext.ExecuteQuery();
To get a better overview on how to do this see - How to: Create, Update, and Delete List Items
I am creating a sample program to check ListItem existence at Sharepoint list.
My SharePoint list has one of column (field) named 'Title' or it can be any other name with text type.
I Know that when we create a list at SharePoint for each item in the list a "ID" field is assigned by SharePoint list item itself.
I am creating my sample application in C# using Microsoft.SharePoint.Client and Microsoft.SharePoint.Client.Runtime dlls.
PROBLEM: I want to get a specific item in the list on the basis of the value of 'Title' column using CAML query.
My List may contains thousands of items,
Using CAML Query :
"<View><Query><Where><Leq>" +
"<FieldRef Name='ID'/><Value Type='Number'>100</Value>" +
"</Leq></Where></Query><RowLimit>7000</RowLimit></View>"
I am successfully retrieving ListItemCollection and throw that I can get ListItem. But its very time consuming and inefficient way, to traverse whole list to get particular item.
Although it is possible to get a specific item in list through the ID field using CAML query, but as i don't know what is the ID of the Item, therefore i want to fetch it through my "Title" field,
for this i tried the following CAML Query
`
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = "<View><Query><Where><eq>" +
"<FieldRef Name='TITLE'/><Value Type='TEXT'>2</Value>" +
"</eq></Where></Query></View>";`
but I get the following exceptions when I run the code
1. Value does not fall within the expected range. this exception is generated when I try to fetch Item through the 'Title' instead of 'ID' field, in the FieldRef Name parameter.
2. One or more field types are not installed properly when i created a coloumn manually in the list, and passed it in the FieldRef Name parameter
My code snippet is as follows
class sharepoint1
{
ClientContext context = null;
string OBJECTMETATADTA_ID = "Title";
private class Configuration
{
public static string ServiceSiteUrl = "";
public static string ServiceUserName = "";
public static string ServicePassword = "";
}
private ListItemCollection getListItemCollectionFromSP(String listName)
{
Web oWebsite = context.Web;
ListCollection collList = oWebsite.Lists;
List oList = collList.GetByTitle(listName);
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = "<View><Query><Where><eq>" +
"<FieldRef Name='Title'/><Value Type='Text'>abc</Value>" +
"</eq></Where></Query></View>";
ListItemCollection collListItem = oList.GetItems(camlQuery);
context.Load(collListItem,
items => items.IncludeWithDefaultProperties(
item => item.DisplayName));
context.ExecuteQuery();
return collListItem;
}
ListItem checkItem(string listname, string fileName)
{
ListItem result = null;
ListItemCollection collListItem =
getListItemCollectionFromSP(listname);
string itemName = fileName.Substring(0, 3);
foreach (ListItem oListItem in collListItem)
{
if (oListItem[OBJECTMETATADTA_ID].Equals(itemName))
{
{
// my business logic;
}
}
}
context.Dispose();
return result;
}
}
It would be great if I get some help on this Issue from any person who knowns about this.
Did you try with 'Eq' instead of 'eq' in your query? CAML query is case sensitive
I am trying to get All Folders and Files from a SharePoint library, executing a single Request.
CamlQuery query = new CamlQuery();
query.ViewXml = "<View Scope='RecursiveAll' />";
var libraryName = "Specific Documents";
ListItemCollection itemsRaw = clientContext.Web.Lists.GetByTitle(libraryName).GetItems(query);
clientContext.Load(itemsRaw);
clientContext.ExecuteQuery();
This code works well, and as result I have a list of All Folders and Files within the specified library.
It seems that the files details are loaded in a lazy manner. Only the first level from details hierarchy. But I don't know how, the FieldValues collection is filled with Data.
I see that the ListItem ContentType.Name is not initialized.
Is it possible somehow to update the query in a manner which will load the data for ContentType in this single call.
Or the only possibility is to iterate through all files and do a load of ContentType for the specific file?
I did this in the following way:
foreach(var listItem in listItemCollection)
{
context.Load(listItem, k => k.ContentType);
context.ExecuteQuery();
var contentTypeName = listItem.ContentType.Name;
}
But I am going to get this information in a single call, If it is possible, without iterating in the collection and starting multiple calls to ClientContext.
P.S.: I am new to SharePoint programming. I just want to fix a bug.
Thanks!
As you correctly noticed in SharePoint Client Side Object Model (CSOM) ClientRuntimeContext.Load Method does not retrieve all the properties for client object.
ClientRuntimeContext.Load Method has the following syntax:
public void Load<T>(
T clientObject,
params Expression<Func<T, Object>>[] retrievals
)
where T : ClientObject
where retrievals parameter is intended for specifying properties that have to be retrieved.
Secondly, since SharePoint CSOM supports Request Batching, your example could be modified to this one:
foreach (var item in items)
{
ctx.Load(item, i => i.ContentType);
}
ctx.ExecuteQuery();
Note: request is submitted to the server only once in this example
But still the provided example requires two requests to the server:
retrieve list items
retrieve content type for list items
and it could be improved from performance perspective by reducing requests to the server till one.
Final example
The example demonstrates how to retrieve list items and specify explicitly which properties to retrieve:
var listTitle = "Documents";
var query = new CamlQuery();
query.ViewXml = "<View Scope='RecursiveAll' />";
var items = ctx.Web.Lists.GetByTitle(listTitle).GetItems(query);
ctx.Load(items,icol => icol.Include(
i => i.ContentType,
i => i.FieldValues));
ctx.ExecuteQuery();
The final example does not work (in SP2010).
There is an exception "The query expression is not supported"
If you explicitly states all required fields then the solution below works.
var listTitle = "Documents";
var query = new CamlQuery();
query.ViewXml = "<View Scope='RecursiveAll' />";
var items = ctx.Web.Lists.GetByTitle(listTitle).GetItems(query);
string[] fieldsToMigrate = new string[] { "Title", "FieldA", "FieldB" };
ctx.Load(items, a => a.Include(b => b.ContentType, b => b["FileRef"]));
foreach (var f in fieldsToLoad) {
ctx.Load(items, includes => includes.Include(a => a[f]));
}
ctx.ExecuteQuery();