SharePoint web services: read version history for column changes
A recent project requirements were to display version history; specifically the value changes in each field, who effected the change, and when it was changed. The first course of action is to enable version history in the list. Once version history is enabled on the list you'll be presented with various UI commands to view the details using the out of the box Versions.aspx page/control. In this particular use-case the application owner wants to present specific field changes in the UI. If we are writing managed code (SSOM) or a Provider Hosted Add-In (CSOM) this would be easy. We focused on customizing the out of the box controls which limits us to JavaScript based solutions. The same technique's apply to SharePoint Hosted Add-Ins as you are limited to REST API's or JavaScript Object Model (JSOM). The first issue with REST or JSOM is a lack of endpoints, extensions, or methods to retrieve Version History. You'll find some stack exchanges which will leverage HTML scraping the Versions.aspx page. The drawbacks to that approach are 1. requiring the List GUID and 2. always expecting the HTML output to render with the specific markup tags. I tried to pull the change history from the (SP.FileVersionCollection) REST API which provide when an item was changed, by whom, and the URL to the item. I couldn't easily get access to the field that was changed so this ultimately left me to leverage SOAP web services. Honestly, this is one area where SharePoint really shines. The engineering team has done a pretty great job ensuring backwards compatibility. I reviewed the documentation for GetVersionCollection from the Lists.asmx web service method. There isn't much documentation in this page but it does provide you with details regarding the SOAP Envelop, method, and expected parameters. The expected parameters are:
- strListID: typically the List GUID but we don't want to parse that out so bonus for us this also accepts the List 'Display Name',
- strListItemID: this is the unique integer value of the List item for which we will retrieve version history
- strFieldName: the Internal Name of the field
The documentation is sparse. You can review the operation by appending the path _vti_bin https://customers.microsoft.com/_vti_bin/lists.asmx?op=GetVersionCollection to your SharePoint site to see the details. The beauty of SOAP was/is self documentation. Included in the service documentation I can see the entire SOAP envelop, required headers, and expected response. Now that I know how to format my request we can proceed with writing code. SPServices provides an extension which will exercise almost all of the SOAP services. Of Note: Marc the author of SPServices has started a blog series detailing the patterns and path forward to REST (so check it out).
Screenshots:
The Versions.aspx page presents the version history for each field
Version history in the browser page
If you are modifying the XSL from an ListViewWebPart you can use the SP Control : AppendOnlyHistory control to render the Field changes with time-stamps.
The output of this XSL markup is presented below. The biggest tweak to the output for this screenshot is the usage of moment.js to render Date Time-stamps. SharePoint stores dates in Coordinated Universal Time (UTC) format. Using moment.js we can display the time-stamp in our local time zone.
SPServices syntax for exercising the GetVersionCollection method. Take a look at the getListItemBySPServices method for the screenshot below.
Pure SOAP AJAX syntax for exercising the GetVersionCollection method. We do have the documentation from the List service so lets construct the request. Take a look at the source getListItemBySoap method for the screenshot below.
We can use the Versions.aspx page with HTML parsing. Take a look at the source getListItemByVersionPage method for the screenshot below.
[caption id="attachment_815" align="alignnone" width="527"] Version History HTML parsing[/caption]
Summary:
Review the source code at https://github.com/pinch-perfect/development-samples/tree/master/Sample06 . You can use this to review the JavaScript, XSL markup, and provision a sample list.
Caveats:
You do not need to use a Multi-line Text with append changes for this code to work appropriately. I used the Multi-line Text column to demonstrate the Append Changes with time-stamps. Once you enable Versioning on a list all columns subscribe to change events. You can use the internal name of any field and retrieve its Field Values. There is a known issue (regarding saving an empty value in the append history) when Versioning and a Multi-line text field with append changes is enabled.