caml query not working properly in sharepoint online - c#

I need to get list items which is older than say 7 days and delete them. I tried using caml query and it worked well in sharepoint 2010 but when I tried to use the same in Sharepoint Online, its getting all list items and deleting it regardless of the condition.
public static bool removeOldEntries(string listName, int offset)
{
bool successFlag = true;
try
{
using (var context = new ClientContext(siteURL))
{
SecureString password = ToSecureString(pwd);
context.Credentials = new SharePointOnlineCredentials(userName, password);
Web web = context.Web;
var list = context.Web.Lists.GetByTitle(listName);
if (list != null)
{
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = "<Where><Leq><FieldRef Name='Modified'/><Value Type='DateTime'><Today OffsetDays='-" + offset + "'/></Value></Leq></Where>";
ListItemCollection collListItem = list.GetItems(camlQuery);
context.Load(collListItem, items => items.Include(
item => item["ID"]));
context.ExecuteQuery();
if (collListItem.Count > 0)
{
foreach (ListItem oListItem in collListItem)
{
ListItem itemToDelete = list.GetItemById(int.Parse(oListItem["ID"].ToString()));
itemToDelete.DeleteObject();
context.ExecuteQuery();
}
}
}
}
}
catch (Exception ex)
{
successFlag = false;
}
return successFlag;
}
Thanks in advance for any help.

First try adding a Tag in your view xml
So it should look like
camlQuery.ViewXml = "<Query><Where><Leq><FieldRef Name='Modified'/><Value Type='DateTime'><Today OffsetDays='-" + offset + "'/></Value></Leq></Where></Query>";
If it doesn't help try adding a view tag
camlQuery.ViewXml = "<View><Query><Where><Leq><FieldRef Name='Modified'/><Value Type='DateTime'><Today OffsetDays='-" + offset + "'/></Value></Leq></Where></Query></View>";

you can make use of the PNP.PowerShell Module.
$CreationDate = Get-Date "16.06.2021 20:04" -Format s
Get-PnPListItem -List "Opportunities" -Query "<View><Query><Where><Eq><FieldRef Name='Created'/><Value Type='DateTime' IncludeTimeValue='FALSE'>$CreationDate</Value></Eq></Where></Query></View>"
For more check out the reference:
https://sposcripts.com/sharepoint/sharepointonline/filtering-for-sharepoint-items-with-caml-queries/#If_DateTime_should_exactly_match_a_specific_date

Related

Unable to Retrieve List Items from SharePoint List Using CAMLQuery in C#

I am Unable to fetch List Items in SharePoint List using CAMLQuery in C#. I have admin rights and able to fetch Column Names of List but getting List Items count as 0.
Can anyone please help me on this? Below is the Code. Here we are getting value of "collListItem" as 0
cc.Load(cc.Web, p => p.Lists);
cc.ExecuteQuery();
var lst = cc.Web.Lists.GetByTitle("Tracker List");
cc.Load(lst.Fields);
cc.ExecuteQuery();
Console.WriteLine("\n Columns \n");
foreach (var item in lst.Fields)
{
if (item.Hidden == false)
{
Console.WriteLine(item.Title);
}
}
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = "<View><Query><OrderBy><FieldRef Name='Created' Ascending='false' /></OrderBy></Query><RowLimit>5</RowLimit></View>";
ListItemCollection collListItem = lst.GetItems(camlQuery);
cc.Load(collListItem);
cc.ExecuteQuery();
Thanks for reply, however its not working for us. We are using app-id and secret for fetching List items and using OfficeDevPnP Nuget for it. We are the owner of SharePoint app and already give FullControl to collection. We are able to get the collection names, Field names of particular List but not ListItems. Sample code snipped for reference.
using OfficeDevPnP.Core;
using Microsoft.SharePoint.Client;
using (var clientContext = new AuthenticationManager().GetAppOnlyAuthenticatedContext(siteUrl, appId, appSecret))
{
CamlQuery caml = new CamlQuery();
caml.ViewXml = "<View><Query><OrderBy><FieldRef Name='Created' Ascending='false' /></OrderBy></Query><RowLimit>5</RowLimit></View>";
var requestItems = clientContext.Web.Lists.GetByTitle(listName).GetItems(caml);
clientContext.Load(requestItems);
clientContext.ExecuteQuery();
foreach (var item in requestItems)
{
Console.WriteLine(item["Title"]);
}
}
Sample demo:
using (var clientContext = new ClientContext("http://sp"))
{
CamlQuery caml = new CamlQuery();
caml.ViewXml = "<View><Query><OrderBy><FieldRef Name='Created' Ascending='false' /></OrderBy></Query><RowLimit>5</RowLimit></View>";
var requestItems = clientContext.Web.Lists.GetByTitle("Test").GetItems(caml);
clientContext.Load(requestItems);
clientContext.ExecuteQuery();
foreach(var item in requestItems)
{
Console.WriteLine(item["Title"]);
}

Should I use one or multiple ClientContext to update a very large List?

I need to update a large SharePoint List, about 10,000 items or more. Each ListItem has 4 columns to be updated. I don't know what the best approach for this scenario is:
Use 1 ClientContext, fetch ListItemCollection in batch of n rows,
loop through each ListItem and update its columns before the next
batch. Or
Fetch a list of ListItemCollectionPosition in batch of n rows, loop through each ListItemCollectionPosition, create a new ClientContext, fetch ListItemCollection and then update.
Method 1
using (ClientContext ctx = new ClientContext(url))
{
ctx.Credentials = new SharePointOnlineCredentials(username,password);
List list = ctx.Web.Lists.GetByTitle("mylist");
ctx.Load(list);
ctx.ExecuteQuery();
ListItemCollectionPosition pos = null;
CamlQuery camlQuery = new CamlQuery
{
ViewXml = "<View Scope='Recursive'><RowLimit>100</RowLimit></View>"
};
do
{
if (pos != null)
{
camlQuery.ListItemCollectionPosition = pos;
}
ListItemCollection listItemCollection = list.GetItems(camlQuery);
ctx.Load(listItemCollection);
ctx.ExecuteQuery();
pos = listItemCollection.ListItemCollectionPosition;
foreach(ListItem item in listItemCollection)
{
item["col1"] = "abc";
item["col2"] = "def";
item["col3"] = "ghi";
item["col4"] = "jkl";
item.Update();
}
ctx.ExecuteQuery();
} while (pos != null);
}
Method 2
private void UpdateList()
{
using (ClientContext ctx = new ClientContext(url))
{
ctx.Credentials = new SharePointOnlineCredentials(username,password);
List list = ctx.Web.Lists.GetByTitle("mylist");
ctx.Load(list);
ctx.ExecuteQuery();
ListItemCollectionPosition pos = null;
CamlQuery camlQuery = new CamlQuery
{
ViewXml = "<View Scope='Recursive'><RowLimit>100</RowLimit></View>"
};
List<ListItemCollectionPosition> positions = new List<ListItemCollectionPosition>();
do
{
if (pos != null)
{
camlQuery.ListItemCollectionPosition = pos;
}
ListItemCollection listItemCollection = list.GetItems(camlQuery);
ctx.Load(listItemCollection);
ctx.ExecuteQuery();
pos = listItemCollection.ListItemCollectionPosition;
positions.Add(pos);
} while (pos != null);
List<Task> tasks = new List<Task>();
foreach(var position in positions)
{
tasks.Add(UpdateItem(position));
}
Task.WaitAll(tasks.ToArray());
}
}
private Task UpdateItem(ListItemCollectionPosition pos)
{
using (ClientContext ctx = new ClientContext(url))
{
ctx.Credentials = new SharePointOnlineCredentials(username,password);
List list = ctx.Web.Lists.GetByTitle("mylist");
ctx.Load(list);
ctx.ExecuteQuery();
CamlQuery camlQuery = new CamlQuery
{
ViewXml = "<View Scope='Recursive'><RowLimit>100</RowLimit></View>"
};
camlQuery.ListItemCollectionPosition = pos;
ListItemCollection listItemCollection = list.GetItems(camlQuery);
ctx.Load(listItemCollection);
ctx.ExecuteQuery();
foreach(ListItem item in listItemCollection)
{
item["col1"] = "abc";
item["col2"] = "def";
item["col3"] = "ghi";
item["col4"] = "jkl";
item.Update();
}
return ctx.ExecuteQueryAsync();
}
}
In method 1 and 2 I would set ViewFields to limit amount of data that is transfered.
In method 2 UpdateItem method is executed after positions collection is full. Why not updating list items while positions collection is being populated - You could implement enumerator with yield attribute.
public static IEnumerable<ListItemCollectionPosition> GetPositions()
{
do
{
...
yield return pos;
...
} while (pos != null);
}

How do I update a Sharepoint ListItem with .Net?

Basically I query Sharepoint and get a list of ListItems. I foreach through the list and check to see if the item needs to be updated from an external db (that code is not present)
Here is the bit of code that I was running that would not update the Sharepoint ListItem. I even tried different credentials to no avail.
using(ClientContext ctx = new ClientContext(searchsiteurl)) {
//NetworkCredential credit = new NetworkCredential(prg.userName, prg.password, prg.domain);
//ctx.Credentials = credit;
Web web = ctx.Web;
List list = web.Lists.GetById(new Guid(site.ListGUID));
var q = new CamlQuery();
if (Fullsync) {
q.ViewXml = "<View><Query><Where><And><BeginsWith><FieldRef Name='SrNumber' /><Value Type='Text'>1</Value></BeginsWith>" + "<Eq><FieldRef Name='_ModerationStatus' /><Value Type='ModStat'>Draft</Value></Eq></And></Where></Query></View>";
}
else {
q.ViewXml = "<View><Query><Where><And><Contains><FieldRef Name='SrNumber' /><Value Type='Text'>1-</Value></Contains><And>" + "<Eq><FieldRef Name='_ModerationStatus' /><Value Type='ModStat'>Approved</Value></Eq>" + "<Gt><FieldRef Name='Modified' /><Value IncludeTimeValue='TRUE' Type='DateTime'>" + last24hours + "</Value></Gt>" + "</And></And></Where></Query></View>";
}
var r = list.GetItems(q);
ctx.Load(r);
ctx.ExecuteQuery();
foreach(SP.ListItem lit in r) {
//do a whole bunch of stuff....
// this does NOT WORK
lit.FieldValues["Linked_x0020_CSRs"] = LinkedSRs;
lit.Update();
ctx.ExecuteQuery();
}
}
The problem with the documentation is that it does not explicitly indicate that you must use the .GetItemById() function to retrieve a ListItem in order to update that ListItem.
So here is the code that should help out future people searching for this answer. It took me waaaay too long to figure this out.
using (ClientContext ctx = new ClientContext(searchsiteurl))
{
//NetworkCredential credit = new NetworkCredential(prg.userName, prg.password, prg.domain);
//ctx.Credentials = credit;
Web web = ctx.Web;
List list = web.Lists.GetById(new Guid(site.ListGUID));
var q = new CamlQuery();
if (Fullsync)
{
q.ViewXml = "<View><Query><Where><And><BeginsWith><FieldRef Name='SrNumber' /><Value Type='Text'>1</Value></BeginsWith>" +
"<Eq><FieldRef Name='_ModerationStatus' /><Value Type='ModStat'>Draft</Value></Eq></And></Where></Query></View>";
}
else
{
q.ViewXml = "<View><Query><Where><And><Contains><FieldRef Name='SrNumber' /><Value Type='Text'>1-</Value></Contains><And>" +
"<Eq><FieldRef Name='_ModerationStatus' /><Value Type='ModStat'>Approved</Value></Eq>" +
"<Gt><FieldRef Name='Modified' /><Value IncludeTimeValue='TRUE' Type='DateTime'>" + last24hours + "</Value></Gt>" +
"</And></And></Where></Query></View>";
}
var r = list.GetItems(q);
ctx.Load(r);
ctx.ExecuteQuery();
foreach (SP.ListItem lit in r)
{
//do a whole bunch of stuff....
/* this does NOT WORK
lit.FieldValues["Linked_x0020_CSRs"] = LinkedSRs;
lit.Update();
ctx.ExecuteQuery();
*/
// this works!
var KAToModify = list.GetItemById(lit.Id);
KAToModify["Linked_x0020_CSRs"] = LinkedSRs;
KAToModify.Update();
ctx.ExecuteQuery();
}
}
it Won`t work you Can use this Enumerator Method
enter code here
foreach (var i in cv)
{
var items = new ListItemCreationInformation();
var item = lists.AddItem(items);
item["Title"] = i.Title;
item.Update();
ctx.Load(item);
ctx.ExecuteQuery();
}`
you will get all your list item you this
if you want particular item in list
you use GetById()

How to retrieve list items from SharePoint 2013

At work we had to move from SharePoint 2010 to 2013 and my code for retrieving list items doesn't work anymore. Here is my code for SP 2010:
com.mycompany.intranet.Lists listService = new com.mycompany.intranet.Lists();
listService.Credentials = System.Net.CredentialCache.DefaultCredentials;
listService.Url = "url";
System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
string listName = cbxMailDistributionList.SelectedValue.ToString();
string viewName = "";
string rowLimit = "0";
System.Xml.XmlElement query = xmlDoc.CreateElement("Query");
System.Xml.XmlElement viewFields = xmlDoc.CreateElement("ViewFields");
System.Xml.XmlElement queryOptions = xmlDoc.CreateElement("QueryOptions");
viewFields.InnerXml = "<FieldRef Name='Title' />";
System.Xml.XmlNode nodeListItems =
listService.GetListItems(listName, viewName, query, viewFields, rowLimit, queryOptions, null);
xmlDoc.LoadXml(nodeListItems.InnerXml);
xlNodeList rows = xmlDoc.GetElementsByTagName("z:row");
List<string> recipients = new List<string>();
foreach (XmlNode attribute in rows)
{
if(attribute.Attributes["ows_Title"].Value == null){}
else {
if (recipients.Contains(attribute.Attributes["ows_Title"].Value)){}
else {
recipients.Add(attribute.Attributes["ows_Title"].Value);
}
}
}
recipients.Sort();
distributionList = recipients;
Can you please help me to get it working with a SharePoint 2013 list again?
URL has already been updated but i get the following error: https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=DE-DE&k=k(EHNullReference);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.0);k(DevLang-csharp)&rd=true
But the list has no empty fields.
listName
is the ID of the list element.
Please help.
Thanks in advance!
Finally it works again with this code:
List<string> recipients = new List<string>();
string siteURL = #"myurl/";
ClientContext cc = new ClientContext(siteURL);
cc.Credentials = System.Net.CredentialCache.DefaultCredentials;
Web web = cc.Web;
List list = web.Lists.GetById(new Guid(cbxMailDistributionList.SelectedValue.ToString()));
CamlQuery caml = new CamlQuery();
ListItemCollection items = list.GetItems(caml);
cc.Load<List>(list);
cc.Load<ListItemCollection>(items);
cc.ExecuteQuery();
foreach (Microsoft.SharePoint.Client.ListItem item in items)
{
if(item.FieldValues["Title"] == null) { }
else
{
if (recipients.Contains(item.FieldValues["Title"].ToString())) { }
else
{
recipients.Add(item.FieldValues["Title"].ToString());
}
}
}
recipients.Sort();
distributionList = recipients;
}
else
{
distributionList = null;
}
New day, new luck. Sorry for the prematurely posting of this question. I should have slept on it for a night. ;)
BR

How can I return differences between versions and access properties that changed?

i have a list in SharePoint 2010 that has fields "title,count" .one of the fields (count) possible to change.
i want to access the last version of this property. by this article: but there are no accepted answer yet.
File file;
FileVersionCollection versions;
ClientContext clientContext;
IEnumerable<Microsoft.SharePoint.Client.FileVersion> oldVersions;
clientContext = new ClientContext(siteUrl);
clientContext.Credentials = new NetworkCredential(user, password, shp.domainname);
Web web = clientContext.Web;
clientContext.Load(web);
clientContext.ExecuteQuery();
string path = web.ServerRelativeUrl + "/Lists/" + listname + "/" + id1 + "_.000"; // it represet list id 7
file = web.GetFileByServerRelativeUrl(path);
ListItem versionListItem = file.ListItemAllFields;
clientContext.Load(versionListItem);
clientContext.ExecuteQuery();
versions = file.Versions;
clientContext.Load(versions);
oldVersions = clientContext.LoadQuery(versions.Where(v => v != null));
clientContext.ExecuteQuery();
if (oldVersions != null)
{
foreach (Microsoft.SharePoint.Client.FileVersion _version in oldVersions)
{
DateTime date = new DateTime();
date = _version.Created.Date;
here i can access to properties but "count" doesn't exist here.
i want to have differences by last versions like SharePoint
i have other method (find it here ) that return for me those last property values
ClientContext clientContext = new ClientContext("http://basesmc2008");
Web site = clientContext.Web;
clientContext.Load(site);
clientContext.ExecuteQuery();
File file = site.GetFileByServerRelativeUrl("/Shared Documents/test.tif");
clientContext.Load(file);
clientContext.ExecuteQuery();
ListItem currentItem = file.ListItemAllFields;
clientContext.Load(currentItem);
clientContext.ExecuteQuery();
FileVersionCollection versions = file.Versions;
IEnumerable<FileVersion> oldVersions = clientContext.LoadQuery(versions.Where(v => v.VersionLabel == "1.0"));
clientContext.ExecuteQuery();
if (oldVersions != null)
{
foreach (FileVersion oldFileVersion in oldVersions)
{
File oldFile = site.GetFileByServerRelativeUrl("/" + oldFileVersion.Url);
clientContext.Load(oldFile);
clientContext.ExecuteQuery();
ListItem oldItem = oldFile.ListItemAllFields;
clientContext.Load(oldItem);
clientContext.ExecuteQuery();
//error here
}
error here
An error has occurred.","ExceptionMessage":"Value does not fall within
the expected range
is there any solution shorter than this for retrieve all last values of specific field?
Sadly actual version data is not available from CSOM. You can get the data by extracting it from /_layouts/Versions.aspx?list={[THE LIST ID]}&ID=[THE ITEMID]&IsDlg=1;
I used HTMLAgilityPack to parse out the data I was looking for (a past value for a specific field)
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(DownloadedPageContent);
HtmlNodeCollection n = doc.DocumentNode.SelectNodes("//tr[#id='vv" + VersionId + FieldName +"']/td");
String value = n[1].InnerText.Trim();

Categories