Retrieving the next page of items with MSGraph - sharepoint-online

I am trying to get a count of the number of items in a Sharepoint List.
I can obtain counts for lists equal to or less than 200. But each page of results contains 200 items and I cannot figure out how to get the next pages.
int listCount = 0;
Microsoft.Graph.List list = new Microsoft.Graph.List();
var queryOptions = new List<QueryOption>()
{
new QueryOption("select", "id"),
new QueryOption("expand", "columns(select=name),items(expand=fields(select=CustomerName))")
};
GraphServiceClient graphServiceClient = GetAuthenticatedGraphClient(scopes).Result;
list = await graphServiceClient.Sites[$"{siteId}"].Lists[$"{listId}"].Request(queryOptions).GetAsync();
if (list.Items != null)
{
listCount = list.Items.Count;
}
I've read through this
https://learn.microsoft.com/en-us/graph/paging
and this
https://learn.microsoft.com/en-us/graph/sdks/paging?tabs=csharp
However #odata.nextLink isn't in the response, and converting the pageIterator code from messages to lists doesn't return any data at all.
The items object does have a field called NextPageRequest, but it is null.
Does anyone please have some example code on how to obtain more pages of Sharepoint List items after the first page?

I found an answer, with some inspiration from
https://github.com/microsoftgraph/msgraph-sdk-dotnet/issues/891
The answer was to request Lists[{}].Items, which retrieves a ListItemsCollectionPage object which contains a count. If that count is 200, then QueryOptions is used in to repeat the request for the next ItemsPage
int listCount = 0;
Microsoft.Graph.IListItemsCollectionPage listItems;
GraphServiceClient graphServiceClient = GetAuthenticatedGraphClient(scopes).Result;
listItems = await graphServiceClient.Sites[$"{siteId}"].Lists[$"{listId}"].Items.Request().GetAsync();
itemCount = listItems.Count();
var nextPage = listItems.NextPageRequest;
while (nextPage != null)
{
listItems = await graphServiceClient.Sites[$"{siteId}"].Lists[$"{listId}"].Items.Request(nextPage.QueryOptions).GetAsync();
itemCount = itemCount + listItems.Count();
nextPage = listItems.NextPageRequest;
}

Related

Netsuite Invoice Line Item not adding

My Restlet should either add or update an invoice with the line items. The add bit works - invoice + line items, but the update doesn't appear to add a new line item. Code looks like this:
update_record = nlapiLoadRecord('invoice', invoice_id)
var itemcount = update_record.getLineItemCount('item');
for (var i = 0; itemcount != null && i < itemcount; i++) {
if (jsonobject.item[i].item) {
update_record.setLineItemValue('item', 'item', i + 1, jsonobject.item[i].item)
}
}
var id = nlapiSubmitRecord(update_record, true);
nlapiLogExecution('DEBUG', 'id = ', id)
return id;
Instead of setLineItemValue, try using the series of selectLineItem, setCurrentLineItemValue, and commitLineItem methods. setLineItemValue is not supported in all scenarios or on all fields.
See the NS Help article titled nlobjRecord for details on all of these methods.

New Calendar Event Does Not Display

I'm using C# and CSOM to build an application that creates an event in a SharePoint calendar that I know exists in my O365 subscription. I know O365 is SharePoint 2013, but my application targets SharePoint 2010, so I'm going to have to deal with both versions.
No exceptions are thrown and everything appears to succeed, but the new event does not display in the calendar, even after a page refresh. If I get a collection of items with the same event title, the program-entered event is returned, and appears to contain all the columns set in code.
The CalendarItemCreate function puts data in all the required columns of the calendar. If I search for other calendar items I have hand-entered through the SharePoint calendar, I find them. The only difference I can see between either hand-entered or program-entered events is the "Description" column has ' for the hand-entered events.
Any ideas?
private void CalendarItemCreate(ICalendarItem item) {
using (var context = new ClientContext(_calendarLocation)) {
context.Credentials = _credentials;
var web = context.Web;
var transferScheduleList = web.Lists.GetByTitle(TransferScheduleToken);
var listItemCreationInformation = new ListItemCreationInformation();
var listItem = transferScheduleList.AddItem(listItemCreationInformation);
listItem[TitleToken] = item.EventTitle;
listItem[EventDateToken] = item.EventStartLocal;
listItem[EndDateToken] = item.EventStartLocal.AddMinutes(30);
listItem[DescriptionToken] = string.Empty; //item.EventDescription;
listItem[TransferTypeToken] = item.EventTransferType;
listItem[TransferStatusToken] = item.EventTransferStatus;
listItem[CategoryToken] = "Data Transfer";
listItem[ConfigurationFileLocationToken] = item.ConfigurationFileLocation;
listItem[EventTypeToken] = 0;
listItem[FallDayEventToken] = false;
listItem[FrecurrenceToken] = false;
listItem.Update();
context.ExecuteQuery();
}
The solution was a combination of formatting the dates as strings that SharePoint could understand and data type mismatches in two of my transfer columns. The code below was successful.
using (var context = new ClientContext(_calendarLocation)) {
context.Credentials = _credentials;
var web = context.Web;
var transferScheduleList = web.Lists.GetByTitle(TransferScheduleToken);
var listItemCreationInformation = new ListItemCreationInformation();
var listItem = transferScheduleList.AddItem(listItemCreationInformation);
listItem[TitleToken] = item.EventTitle;
listItem[EventDateToken] = item.EventStartLocal.ToUniversalTime().ToString(#"yyyy-MM-ddTHH:mm:ssZ");
listItem[EndDateToken] = item.EventStartLocal.AddMinutes(30).ToUniversalTime().ToString(#"yyyy-MM-ddTHH:mm:ssZ");
listItem[DescriptionToken] = item.EventDescription;
listItem[TransferTypeToken] = item.EventTransferType.ToString();
listItem[TransferStatusToken] = item.EventTransferStatus.ToString();
listItem[CategoryToken] = "Data Transfer";
listItem[ConfigurationFileLocationToken] = item.ConfigurationFileLocation;
listItem[EventTypeToken] = 0;
listItem[FallDayEventToken] = false;
listItem[FrecurrenceToken] = false;
listItem.Update();
context.ExecuteQuery();

Search not working on item record

I am not able to get the list of item.I am using a saved search and want to create a list of all the item record id from it.
But it is not working.
my code
var loadSearch=nlapiLoadSearch('item','customsearch12');
var getData = loadSearch.runSearch();
var itemCol=new Array();
for(var i=0;i<getData.length;i++)
{
itemCol.push(getData[i].getId());
}
Can somebody help me with this
try this code
var loadSearch=nlapiLoadSearch('item','customsearch12');
var getData = loadSearch.runSearch();
var itemCol=new Array();
getData.forEachResult(function (searchRow) {
itemCol.push(searchRow.getId());
return true;
});
when you use a nlapiLoadSearch, the result is nlobjSearchResultSet and not an array like in the case of nlapiSearchRecord.
if you use nlapiSearchRecord, then you can loop through the result like you were trying in your code, i.e. using index
The answer given above by Nitish is perfectly correct but you need to consider one more thing.
nlapiLoadSearch api returns 4000 records at a time.
The nlapiSearchRecord api returns only 1000 records at a time , so what if your saved search consists of more than 1000 records.
So you will miss those extra items.
so here is the code to have better results
//Searching the items
var searchResults = nlapiSearchRecord('item', 'customsearch12',null,null);
var searchedItemId;
var lastId;
var completeResults = new Array();
var arrNewFilters=[];
if (searchResults != null) {
completeResults = completeResults.concat(searchResults);
}
else {
completeResults = null;
nlapiLogExecution('Debug', 'No item found',
weight + ' Null result');
}
if (completeResults != null) {
if (searchResults.length == 1000) {
while (searchResults.length == 1000) {
//Initialize variable
lastId = "";
//Get Record Id of Last record,
//to search the item record again from that record
lastId = searchResults[999].getId();
//start after the last id searched
arrNewFilters.push(new nlobjSearchFilter("internalidnumber",
null, "greaterthan", lastId));
//Lets search again
var searchResults = nlapiSearchRecord('item', 'customsearch12',
arrNewFilters, null);
if (searchResults != null) {
//Append the search result to the result present before
completeResults = completeResults.concat(searchResults);
}
}
}
for (var result = 0; result < completeResults.length; result++) {
//Loop through the items
}
Hope you got me Nitish!!!
Here's a sample of how to fetch over 1k of results in NetSuite/NetScript.
The search "customsearch_tel_tg_by_trunk_type" is not really relevant.
Complete sample of 1k+ results fetch in NetSuite/NetScript
You could get all the results one by one using a callback function till all the records are iterated.
var search = nlapiLoadSearch('item','customsearch12');
var resultSet = loadSearch.runSearch();
var itemCol=new Array();
resultSet.forEachResult(function (iterator) {
itemCol.push(iterator.getId());
return true;
});
or you could load few records of it using the getResults of the nlobjResultSet
var search = nlapiLoadSearch('item', 'customsearch12');
var resultSet = search.runSearch();
var results = resultSet.getResults(0, 100);//get the results from 0 to 100 search results
var itemCol = new Array();
for(var i in results)
{
itemCol.push(results[i].getValue('id'));
}

How to add a term to TermCollection (taxonomy field)

In sharePoint 2010, I want to set taxonomy values of a document field. The field can take multiple taxonomy terms.
I am doing it the wrong way because the cast of taxoTerms.Concat(terms) in TermCollection class fails :
TaxonomyField taxoField = file.Item.Fields.GetFieldByInternalName(entry.Key)
as TaxonomyField;
TaxonomySession taxoSession = new TaxonomySession(web.Site);
TermStore store = taxoSession.TermStores[taxoField.SspId];
TermSet termSet = store.GetTermSet(taxoField.TermSetId);
if (taxoField.AllowMultipleValues)
{
string[] taxoValues = entry.Value.Split(';');
TermCollection taxoTerms = termSet.GetTerms(taxoValues[0], true);
for (int j = 1; j < taxoValues.Length; j++)
{
TermCollection terms = termSet.GetTerms(taxoValues[j], true);
if (terms.Count > 0)
{
taxoTerms = (TermCollection)taxoTerms.Concat(terms);
}
}
taxoField.SetFieldValue(file.Item, taxoTerms);
}
Do you know how can I add terms to my TermCollection object so I can save the term values in the field ?
I found my solution. Here it is :
TaxonomyField taxoField =
file.Item.Fields.GetFieldByInternalName(entry.Key) as TaxonomyField;
TaxonomySession taxoSession = new TaxonomySession(web.Site);
TermStore store = taxoSession.TermStores[taxoField.SspId];
TermSet termSet = store.GetTermSet(taxoField.TermSetId);
if (taxoField.AllowMultipleValues)
{
string[] taxoValues = entry.Value.Split(';');
TermCollection terms = termSet.GetAllTerms();
List<string> taxonomyValueList = taxoValues.ToList<string>();
TaxonomyFieldValueCollection fieldValues = new TaxonomyFieldValueCollection(taxoField);
foreach (Term term in terms)
{
if (taxonomyValueList.Contains(term.Name))
{
TaxonomyFieldValue fieldValue = new TaxonomyFieldValue(taxoField);
fieldValue.TermGuid = term.Id.ToString();
fieldValue.Label = term.Name;
fieldValues.Add(fieldValue);
}
}
taxoField.SetFieldValue(file.Item, fieldValues);
}
Hope it helps others.
Here is a sample that could work:
var item = file.Item;
var taxonomyField = item.Fields.GetFieldByInternalName(entry.Key);
var values = new TaxonomyFieldValueCollection(taxonomyField);
values.PopulateFromLabelGuidPairs(entry.Value);
item[entry.Key] = values;
item.Update();
I did not test it on a life system so there can be some additional work, but I hope you get the general idea. The values in the entry.Value string have to contain the | and ; separated list of tags. If the tag does not exist you have to create it and get its id before you save it to the item.
HTH
Vojta

Re-order the column numbers when item deleted in sharepoint list

I have a list "Numbers". Items in this list are from 1 to 10(a column other than ID will display this number).
item[1st item]["order"]=1;item[2nd item]["order"]=2;......item[10th item]["order"]=10;
If any item got deleted, lets say item[6th item]["order"]=6; got deleted, then the items in that list should be 1 to 9 i.e. when the item gets deleted, automatically have to order these values. Here i am using ItemDeleted Event Handler to achieve this functionality. But its not working. My code is :
public override void ItemDeleted (SPItemEventProperties properties)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
string mysiteUrl = properties.WebUrl;
SPSite mysite = new SPSite(mysiteUrl);
SPWeb myweb = mysite.OpenWeb();
myweb.AllowUnsafeUpdates = true;
SPList mylist = myweb.Lists["Numbers"];
for (int i = 0; i < mylist.ItemCount; i++)
{
int order = int.Parse(mylist.Items[i]["order"].ToString());
if (!(i + 1 == order))
{
int categoryId = int.Parse(mylist.Items[i]["ID"].ToString());
SPListItem item = mylist.GetItemById(categoryId);
item["Priority"] = i + 1;
mylist.Update();
}
}
myweb.AllowUnsafeUpdates = false;
});
}
I installed and activated the feature. But its not working. I dont know what going wrong here.Please help me on this issue
Try calling Update() on the SPListItem and not the SPList

Resources