Goal: to be able to relate a ChangeItem from a Changelog to a version of that item.
Issue: I can fetch metadata and version for a List Item. However, I am unable to relate a specific version of that list item to the Change Item, i.e. a specific change which was performed on the item.
For example:
If I have versions 1, 2 and 3 of a Document list item of list item id 3, and I get a change log for version 2, then how to I relate the ChangeItem for list item id 3 to version 2?
What I have done so far
Query the change log
_cc = new ClientContext(url);
_cc.AuthenticationMode = ClientAuthenticationMode.Default;
_cc.Credentials = new SharePointOnlineCredentials(userName, password);
ListCollection lists = _cc.Web.Lists;
IEnumerable<List> results = _cc.LoadQuery<List>(lists.Where(lst => lst.Title == listName));
_cc.ExecuteQuery();
List list = results.FirstOrDefault();
if (list == null)
{
Console.WriteLine("A list named \"{0}\" does not exist. Press any key to exit...", listName);
Console.ReadKey();
return;
}
nextRunTime = DateTime.Now;
ChangeQuery cq = new ChangeQuery(true, true);
cq.Item = true;
cq.DeleteObject = true;
cq.Add = true;
cq.Update = true;
// Initially set the ChangeTokenStart to 2 days ago so we don't go off and grab every item from the list since the day it was created.
// The format of the string is semicolon delimited with the following pieces of information in order
// Version number
// A number indicating the change scope: 0 – Content Database, 1 – site collection, 2 – site, 3 – list.
// GUID representing the scope ID of the change token
// Time (in UTC) when the change occurred
// Number of the change relative to other changes
cq.ChangeTokenStart = new ChangeToken();
cq.ChangeTokenStart.StringValue = string.Format("1;3;{0};{1};-1", list.Id.ToString(),
DateTime.Now.AddDays(-2).ToUniversalTime().Ticks.ToString());
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(string.Format("Ctrl+c to terminate. Press \"r\" key to force run without waiting {0} seconds.", WaitSeconds));
Console.WriteLine();
Console.ResetColor();
do
{
do
{
if (Console.KeyAvailable && Console.ReadKey(true).KeyChar == 'r') { break; }
}
while (nextRunTime > DateTime.Now);
Console.WriteLine(string.Format("Looking for items modified after {0} UTC", GetDateStringFromChangeToken(cq.ChangeTokenStart)));
ChangeCollection coll = list.GetChanges(cq);
_cc.Load(coll);
_cc.ExecuteQuery();
DisplayChanges(coll, cq.ChangeTokenStart);
// if we find any changes to the list take the last change and use the ChangeToken as the start time for our next query.
// The ChangeToken will contain the Date/time of the last change to any item in the list.
cq.ChangeTokenStart = coll.Count > 0 ? coll.Last().ChangeToken : cq.ChangeTokenStart;
nextRunTime = DateTime.Now.AddSeconds(WaitSeconds);
} while (true);
Query Item Metadata
private static void DisplayChanges(ChangeCollection coll, ChangeToken ct)
{
if (coll.Count == 0)
{
// Console.WriteLine(string.Format("No changes to {0} since {1} UTC.", listName, GetDateStringFromChangeToken(ct)));
return;
}
Console.ForegroundColor = ConsoleColor.Green;
// https://msdn.microsoft.com/en-us/library/office/bb417456(v=office.14).aspx
foreach (var itm in coll)
{
if (itm is ChangeItem)
{
// Get the list for this item and determine whether versioning is turned on
var c_item = itm as ChangeItem;
GetVersion(c_item.ListId, c_item.ItemId, c_item.Time);
}
Get version This is where I am unclear about how to relate a ChangeItem back to a specific version of that change. Any ideas ??
private static void GetVersion(Guid listid, int itemId, DateTime time)
{
var list = _cc.Web.Lists.GetById(listid);
var listItem = list.GetItemById(itemId);
_cc.Load(listItem, i => i.DisplayName);
// ExecuteQuery will pull all data from SharePoint
// which has been staged to Load()
_cc.ExecuteQuery();
File fileItem = listItem.File;
FileVersionCollection fileVersions = fileItem.Versions;
_cc.Load(fileVersions);
_cc.ExecuteQuery();
if (fileItem.Versions.Count > 0)
{
foreach (var version in fileItem.Versions)
{
// Unclear how to relate the version back to the ChangeItem
if (version.Created.Equals(time))
{
Console.WriteLine("Item {0} Version {1}", listItem.DisplayName, version.VersionLabel);
}
}
//Console.WriteLine("Item {0} Version {1}", listItem.DisplayName, fileItem.Versions[fileItem.Versions.Count - 1].VersionLabel);
}
}