SPChangeQuery is a great little function that queries the SharePoint change log for changes to site content. Be careful when using the SPChangeQuery on newly created sites as certain content may get picked up in your query that is garbage to you. This includes a bunch of “add” change types on lists that get initialized after site creation.

Unfortunately there is no easy way of knowing when the system generated “changes” end (from the site creation) and your user “changes” begin (assuming that is all you are interested in).

If you disregard all changes relating to the following lists you can eliminate such garbage

  • User Information List
  • Web Part Gallery
  • Master Page Gallery
  • Reporting Templates
  • Reporting Metadata

I remove them by checking if the changed item’s list name is equal to any of those listed above. Lastly, don’t forget those annoying SharePoint images:

  • “Get Started with Windows SharePoint Services!”

I put a special case in to disregard this as well.

An example function is below. This is a function I use in a web part (a proof of concept – please take its level of design and completeness with a grain of salt) that I created that displays recent activity for a particular site, featured in the image below.

Recent Changes Web Part

Recent Changes Web Part

If you find the code below hard to view you can also view it on a more friendly page here. There is  horizontal scroll bar at the bottom of the post so you can see the text that goes out of the usual wrapping bounds.

If anyone would like the full web part please post a comment, I am happy to go through it on an upcoming post.

///
/// Gets the recent changes for the web in context occuring in the given timespan.
///
private string[] getRecentChangesWeb(TimeSpan timespan)
{
   ArrayList result = new ArrayList();
   SPSite siteCollection = SPContext.Current.Site;
   SPWeb site = SPContext.Current.Web;
   SPListCollection lists = site.Lists;
   SPRegionalSettings regionSettings = site.RegionalSettings;
   SPTimeZone timeZone = regionSettings.TimeZone;
 
   /// Get all the changes in the last timespan
   /// If the site collection has been created in the last 24 hours then
   /// make sure you are only getting changes that have occured after it has been set-up
 
   SPChangeToken token = new SPChangeToken(SPChangeCollection.CollectionScope.Web, site.ID, DateTime.Now - timespan);
   SPChangeQuery query = new SPChangeQuery(true, true);
   query.ChangeTokenStart = token;
 
   SPChangeCollection changes = site.GetChanges(query);
 
   foreach (SPChange changedObject in changes)
   {
      switch (changedObject.GetType().ToString())
      {
         case "Microsoft.SharePoint.SPChangeItem":
 
            SPChangeItem changedItem = (SPChangeItem)changedObject;
            try
            {
               if ((string.Compare(lists[changedItem.ListId].Title, "User Information List") != 0) &&
                  (string.Compare(lists[changedItem.ListId].Title, "Web Part Gallery") != 0) &&
                  (string.Compare(lists[changedItem.ListId].Title, "Master Page Gallery") != 0) &&
                  (string.Compare(lists[changedItem.ListId].Title, "Reporting Templates") != 0) &&
                  (string.Compare(lists[changedItem.ListId].Title, "Reporting Metadata") != 0) &&
                  (string.Compare(lists[changedItem.ListId].GetItemByUniqueId(changedItem.UniqueId).Name, "Get Started with Windows SharePoint Services!") != 0)))
                  {
                     string str;
                     SPUserCollection users = site.AllUsers;
 
                     switch (changedItem.ChangeType)
                     {
                        /// create a string that represents the adding of an item
                        case SPChangeType.Add:
 
                           str = lists[changedItem.ListId].GetItemByUniqueId(changedItem.UniqueId)["Created By"].ToString();
                           /// get the user
                           SPUser user1 = users.GetByID(Convert.ToInt32(str.Split(';')[0]));
 
                           /// get their My Site public URL if it exists
                           Uri mysiteUri = getUserPublicMySite(user1.LoginName, siteCollection);
 
                           result.Add((string)"<a href=\" + str.Split('#')[1] + "</a>created \"" + lists[changedItem.ListId].GetItemByUniqueId(changedItem.UniqueId).Name + "\" at " + timeZone.UTCToLocalTime(changedItem.Time));
                           break;
 
                        /// do for more change types...
                        /// case SPChangeType.Update:
                     }
                  }
               }
               catch
               {
                  Console.WriteLine("The object to which item " + changedItem.UniqueId + " belongs does not exist.");
               }
            break;
 
         }
      }
      return (string[])result.ToArray(typeof(string));
   }/// end getRecentChanges
Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • LinkedIn
  • Technorati
  • Twitter
  • MySpace
  • RSS
  • Twitthis

Tags: , , , , , ,

4 Comments to “Using SPChangeQuery in a new Site (SPWeb)”

  1. Carol says:

    Hi Scott,

    I am wondering why the Change Type is not shown as “ADD” when a new site is created.

    I am working with SPChange class and calling GetChanges on every site collection.

    Results look like:(for new site created under sitecollection)

    The object type is shown as SPChangeWeb
    The Change Type is shown as “Navigation”.

    Is this a bug ?
    Can you help me with this. How to know that a new site has been added using GetChanges()

    Thanks
    Carol

    • Carol,

      Thanks for the comment. To the best of my knowledge, the addition of a site is not logged as a change. If you have a look at SPChangeType Enumeration on MSDN, you can see that the “Add” change type only relates to items being added to a specific scope. The change you are seeing is generated when SharePoint makes a change to the global navigation when you add a new site. I suspect that if you do not inherit the local or global navigation when you create a new site, you may not see any change recorded (try it and let me know what you find).

      If you use the Publishing feature, you will see the creation of new pages logged as an “Add” change type because these are being created in the Pages list (instantiated by the Publishing feature when activated).

      If you want to track the creation of SPWebs as a change that you can pull out of an SPChangeQuery, you may want to investigate adding a record to the dbo.eventlog table in the appropriate content database (SPChangeQuery is querying this table for its events). I would add the record in a feature that is stapled to the “GLOBAL” site definition (this will execute the feature on all sites, although I have heard reports that GLOBAL site definition does not include blank sites). If I were to hazard a guess I would say that this would be an unsupported solution from Microsoft’s perspective as you would be directly accessing the content database to write the record…

      Hope this helps, let me know how you go. If you have any more questions I am more than happy to answer them.

      Regards,
      Scott

      • Carol says:

        Hi Scott,

        Thanks a lot for your help. When I saw the results in a Console I am not able to see the ADD.

        But in the actual back end I developed using Switch statements for each Object Type and Change Type, I was able to see “ADD” event logged.

        But now I am stuck up with Deletes, i am not able to see any information except the ID of the change object.
        I am not able to get the other information like URL and child items that are also deleted.

        Can you help me with this by sharing your ideas?

        Thanks again for you time.

        Thanks
        Carol

  2. Carol says:

    Hi Scott,

    Thanks a ton for your response.

    Actually I am not able to see that when I do this-

    foreach (SPChange change in changes)
    {
    Console.WriteLine(“\r\nDate: {0}”, timeZone.UTCToLocalTime(change.Time).ToString());
    Console.WriteLine(“Object type: {0}”, change.GetType().ToString());
    Console.WriteLine(“Change type: {0}”, change.ChangeType);
    }

    But when I did this

    switch (objType.Name)
    {
    case “SPChangeWeb”:
    {
    SPChangeWeb changeWeb = change as SPChangeWeb;
    Guid owebId = changeWeb.Id;
    var Q = from SPWeb oweb in ositeCollection.AllWebs
    where oweb.ID == owebId
    select oweb;

    Now it is working, it is logging as “Add” now

Using SPChangeQuery in a new Site (SPWeb) : Leave a Reply

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">