Microsoft SharePoint incluye un “change log” para hacer tracking de los cambios sobre listas, Web site, site collection, o content database (no soportado sobre Office 365). Por ejemplo, si un item es agregado a una lista, actualizado, renombrado, movido o borrado. Esta información es guardada en el change log junto con la hora que se realizó el cambio y un identificador único para el item.
El uso de change log de Sharepoint, no siempre es el más apropiado para algunos escenarios, ya que se puede usar otras soluciones, tales como event receivers o workflows.
Por default la información se almacena por 60 días. Pueden ver un overview en el siguiente link:
https://msdn.microsoft.com/en-us/library/office/bb417456(v=office.14).aspx (algunas cosas no están soportadas por Office 365.)
En Office 365 tenemos disponibles los siguientes métodos:
Cada método retorna una colleción de objetos, que son descendientes del objeto al cual se hizo referencia. Ej: si yo utilizo List.GetChanges, sólo retornará cambios realizados sobre la lista que se le pasó como parámetro, y NO cambios de otras listas.
Las propiedades del objeto ChangeQuery pueden dividirse en dos: change actions y objetos cambiados.
Change Actions (https://msdn.microsoft.com/en-us/library/office/bb447550(v=office.14).aspx#sectionSection2)
- Add
- DeleteObject
- GroupMembershipAdd
- GroupMembershipDelete
- Move
- Rename
- Restore
- RoleAssignmentAdd
- RoleAssignmentDelete
- RoleDefinitionAdd
- RoleDefinitionDelete
- RoleDefinitionUpdate
- SystemUpdate
- Update
Objetos cambiados (https://msdn.microsoft.com/en-us/library/office/bb447550(v=office.14).aspx#sectionSection1):
- Alert
- ContentType
- Field
- File
- Folder
- Group
- Item
- List
- Navigation
- SecurityPolicy
- Site
- User
- View
- Web
El método ChangeQuery tiene el siguiente encabezado
Si yo uso ChangeQuery siteCQ = new ChangeQuery(true, true);: voy a buscar todos los cambios de todos los objetos.
En cambio si uso ChangeQuery siteCQ = new ChangeQuery(false, false): puedo definir que cambios de acciones buscar y que objetos.
Ej: siteCQ.Item = true (sólo busco items cambiados)
Ej: siteCQ.DeleteObject = true; (busco acciones de borrado de objetos)
Veamos un ejemplo con Sharepoint Online, con Sharepoint On-premise es similar, sólo cambia la manera de hacer login y algunos eventos más (Ej: para content database o web applications)
Con las siguientes dos líneas, estoy indicando que voy a traer todos los cambios de todos los objetos, y lo haré desde el site collection para abajo.
ChangeQuery siteCQ = new ChangeQuery(true, true);
var siteChanges = site.GetChanges(siteCQ);
La siguiente línea, indica, que si el cambio es de tipo ChangeItem, lo proceso. Se puede hacer por cada tipo de cambio.
if (change is Microsoft.SharePoint.Client.ChangeItem)
{
}
El resultado es el siguiente:
También es posible limitar los cambios desde un inicio hasta un final, o desde la última vez que se ejecutó.
Ej:
// Construct a query.
SPChangeQuery query = new SPChangeQuery(false, // Specify object types
false // Specify change types
);
// Specify object types.
query.User = true;
query.Group = true;
// Specify change types.
query.Add = true;
query.Delete = true;
query.Update = true;
query.GroupMembershipAdd = true;
query.GroupMembershipDelete = true;
query.ChangeTokenStart = lastProcessedToken
En el caso que quisieramos limitar los resultados entre dos tokens de ejecución, puedo usar la propiedad ChangeTokenEnd
Para mantener el último token procesado, podemos ver el siguiente ejemplo, el cual usa un archivo .dat para almacenar el último token ejecutado.
https://msdn.microsoft.com/en-us/library/office/ff408387(v=office.14).aspx
Para mayor información:
https://msdn.microsoft.com/en-us/library/office/microsoft.sharepoint.client.changequery_members.aspx
https://msdn.microsoft.com/en-us/library/office/bb447550(v=office.14).aspx
Código Fuente:
using (ClientContext clientContext = new ClientContext(ConfigurationManager.AppSettings["SiteUrl"]))
{
SecureString passWord = new SecureString();
foreach (char c in ConfigurationManager.AppSettings["Password"].ToCharArray()) passWord.AppendChar(c);
clientContext.AuthenticationMode = ClientAuthenticationMode.Default;
clientContext.Credentials = new SharePointOnlineCredentials(ConfigurationManager.AppSettings["Usuario"], passWord);
var site = clientContext.Site;
clientContext.Load(site);
ChangeQuery siteCQ = new ChangeQuery(true, true);
var siteChanges = site.GetChanges(siteCQ);
clientContext.Load(siteChanges);
clientContext.ExecuteQuery();
foreach (Change change in siteChanges)
{
//Console.WriteLine("{0}, {1}, {2}",change.Time, change.ChangeType, change.TypedObject);
if (change is Microsoft.SharePoint.Client.ChangeItem)
{
ChangeItem ci = change as ChangeItem;
Console.WriteLine("Sobre el Item {0} (lista {1}) se ejecutó la siguiente acción {2}", ci.ItemId.ToString(), ci.ListId.ToString(), ci.ChangeType);
}
if (change is Microsoft.SharePoint.Client.ChangeList)
{
ChangeList cl = change as ChangeList;
Console.WriteLine("Sobre la lista {0} se ejecutó la siguiente acción {1}", cl.ListId.ToString(), cl.ChangeType);
}
}
}