logo

SharePoint: Record Changes at Field Level in A List Item

Out of the box SharePoint displays basic revision history on List Items, which looks a bit like this:

image

It tells you who created it along with who last modified it. Useful information but not always enough. Sometimes you want a full list of the names and dates of all revisions.

Sometimes you want to go further still and track changes in the value of a specific field too. The "status" field, let's say. This might look something like the image below, where the Revisions section of the Item lists all changes along with (if applicable) what the value of the Status field was before and after.

image

In most technologies this is quite a basic task. With SharePoint, unless I'm missing something, this was anything but simple.

What I'll describe here is how I went about adding the above Revisions section to a List Item.

Disclaimer: I'm not suggesting this is the only way or the best way to achieve this. I'm a noob at SharePoint and learning as I go. Feel free to use this approach or to point me in the right direction.

How?

First thing we need is a new type of Field. From within a WSPBuilder project in Visual Studio add a new "Custom Field Type" as below:

image 

After you click the Add button an XML file should appear. Make the changes highlighted below:

image

We changed the parent type of this field to "Note" which means it will act like a large multiline field with no restriction on text size.

Now, in the project structure there should be a folder called 12\template\controntemplates. The folder should have a file in it called RevisionHistoryFieldEditor.ascx. Edit this file to get rid of/replace (or hide) the example DropDown it contains. Once you're done, build the WPS package and deploy it, using the right click options of the WSPBuilder project.

Back in the SharePoint web site go to Site Settings and find the Content Type you want to add this field to. Open the Content Type and in the Columns section find the link to "Add from new site column". The page that follows lets you add a new Column and should list our new field type, as highlighted below:

image

Once you're done on that page you should see this new field on any Items based on the Content Type you added it to.

There you go - that's the easy part done!

Now we need to start logging the revisions to this field. To do this we'll use an Event Handler. Start by creating a new one, like so:

image

This will add a new folder containing the XML to describe this feature along with a folder containing the .CS file with the code for the handler.

In the newly-created XML file call elements.xml change it to look like this:

image

The handler now knows to only listed for events triggered by an item being updated.

Now, open the .CS file that shares the same name as the Event Handler you created. Find the ItemUpdating function and replace it with this code:

public override void ItemUpdating(SPItemEventProperties properties)
{
 try
 {

  SPList list = properties.OpenWeb().Lists[properties.ListId];
  SPListItem item = list.GetItemById(properties.ListItemId);

  if (item.Fields.ContainsField("StepStatus")){ //Must be the type of Item we're interested in!?

   string changeLog = "Revised by " + properties.UserDisplayName + " on " + DateTime.Now.ToString()+".";

   //BeforeProperties doesn't work for Lists! WTF!!
   if (properties.ListItem["StepStatus"[!=null && (properties.ListItem["StepStatus"].ToString() != properties.AfterProperties["StepStatus"].ToString()))
   {
    changeLog += " Status changed from " + properties.ListItem["StepStatus"].ToString() + " to " + properties.AfterProperties["StepStatus"].ToString() + ".";
   }

   properties.AfterProperties["StepRevision"] = 
        ((item.Fields.ContainsField("Revisions"))?properties.ListItem["Revisions"]:"") 
        + changeLog + "\n";
  }
 }
 catch (Exception e)
 {
  properties.ErrorMessage = e.StackTrace;
  properties.Status = SPEventReceiverStatus.CancelWithError;
  properties.Cancel = true;
 }
}

What this does is look for changes to the type of list Item we're interested in and then appends a change log to the field with the name by which we called the field we added earlier.

With the code in place you need to build the WSP project, deploy it and then enable the new feature in the site admin area.

Summary

Believe it or not I've made this sound easier than it actually is! In reality it's a bit trickier as you need to deploy, build and debug the feature. However, what I've outlined above is what I believe to be a half decent solution to this problem. Whether there's a better one I don't know. Trust me when I say I had a good hard look for one before I started down the DIY route.

Comments

    • avatar
    • Ulf
    • Tue 3 Aug 2010 07:10 AM

    Just never try to change that Custom Field Definition later, and redeploy it.

  1. Jake, I believe you are going to find the DIY approach is the common approach unless you find an existing web part someone else has created. The .NET framework, from what I have seen, does so much thinking for the developer that two issues arise. Firstly, development can be achieved with little thought if little customization is desired. Secondly, anything that the SharePoint.NET core team has not thought of is going to be inherently a lot of work by comparison because you have to build up the piece of the framework you find lacking from the .NET level up.

    Understanding that SharePoint is essentially an ASP.NET extension (a framework upon a framework) helps us realize this should be no surprise. It's looking to me like I go out and buy a simple two door car and realize a month in that I need a third door and then have a lot of sheet metal work ahead of me to get one (because I'm apparently damned if I think I can take the car back.) The recurring theme is that SharePoint is gorgeous out of the box but is what it is and not much more. The "much more" is all on the back of the developer, or so it would seem.

    • avatar
    • Chris Brewer
    • Tue 3 Aug 2010 03:09 PM

    Simplified way that uses OOTB SharePoint:

    Use a "Multiple lines of text" column type with "Append" on. Then in SharePoint Designer create a "Run when items updated" workflow on the list to add an "entry" to the Revisions field. You can then use SPD to customise the New and Edit forms so that the Revisions field is read-only.

    A major drawback with this method is that SPD workflows can only be attached to specific lists (as opposed to Browser-based workflows that can be attached to content types) so if you have multiple lists you'll need to duplicate the workflow for each list (in which case your way would be better).

  2. Wait til you try to reproduce controlled access sections !

    • avatar
    • Shayne
    • Wed 24 Aug 2011 06:22 PM

    Turning on Version History will keep a record of every change.

    To see what was previously done, select the Item and select Version History.

    It doesn't fill up the Item either

    i.e. if 50 changes were made in the example above, your Item window would grow quite large.

Your Comments

Name:
E-mail:
(optional)
Website:
(optional)
Comment:


About This Page

Written by Jake Howlett on Tue 3 Aug 2010

Share This Page

# ( ) '

Comments

The most recent comments added:

Skip to the comments or add your own.

You can subscribe to an individual RSS feed of comments on this entry.

Let's Get Social


About This Website

CodeStore is all about web development. Concentrating on Lotus Domino, ASP.NET, Flex, SharePoint and all things internet.

Your host is Jake Howlett who runs his own web development company called Rockall Design and is always on the lookout for new and interesting work to do.

You can find me on Twitter and on Linked In.

Read more about this site »

More Content