As of 7-13-2016 A version of this technology named RemarQ is now available for SharePoint 2013 and 2016, it is on GitHub at this url https://github.com/BalsamicSolutions/RemarQ/

Project Description
I have always been disappointed that SharePoint does not provide an underlying technology for deciding if a SharePoint item has been read by the current user. To fill that need, this project is a SharePoint site column and some supporting technology to provide visual indicators in a standard CAML view for whether or not the current user has read a specific item. It started out as an extension to the Freeze Dried Site Column project, but as it developed I realized that it would require a storage format query-able by the standard CAML view syntax. So I ended up with a separate project, which shares some code with the freeze dried project but is distributed separately.



There are a number of display configuration options, but in its basic mode it attempts to highlight unread rows by setting their bold attribute. For it to work, the column must be added to the list, and it must appear somewhere in the active view. The column also must appear on the new and display forms of the item edit so that it can set the read indicators for the current user. Luckily, all of this happens by “default” if you add the column to the current list. I have not figured out how to make the column sortable or filterable yet( I am still working on that and if you have any ideas feel free to pitch in). The only warning I will give you, is that I had to “cheat” in a few places, and we all know cheating with API calls is sometimes dangerous. If you poke around in the cheats you will see that they look pretty safe to use (more on this later), but consider yourself warned. Along with the cheats, I am kind of proud of the CAML; it renders an inline user interface for setting and clearing read marks from the list view. To set it up, simply compile the project. In debug mode the post build event will push the assembly to the GAC and register the column and column property pages.  In Release mode, it will build a WSP solution file for you to deploy. Once the solution is available, simply add a Read Unread column it to a list (not a library), the default configuration will work fine but of course you can configure it several different ways. From then on, it will track read and unread marks for that list item for all of the SharePoint built in forms. If you have a customized form, you need to put the field on it as well so it can track readers.

How it works:
The storage column is a SharePoint note field, and in that column we store the numerical user Id for all users that have read the item. The Id’s are separated by a delimiter (in this case a period) but are otherwise stored as a string. In “New” mode the field control adds the current user to the field, in “Display” mode the field control also adds the current user to the field. There is some odd code here for manipulating the field without corrupting other sessions (which is where the cheating comes in). There is also an option that can be selected that will configure an event handler for the list automatically. The even handler clears the read marks if any of the content is updated. The CAML that renders the column emits JavaScript for marking things bold if they are unread, and a small checkbox that posts back to a layouts page that can also set or clear users’ read mark (it posts back to a layouts page).

The “Cheats”:
There are two cheats (a little one and a big one). The first issue I ran into is that any update to the read marks column triggered SharePoint event listeners. While it would have been easy to bypass that for our events, other event handlers may be needed for the list and we don’t want to fire them when our column data was changed. Obviously we could have moved our read marks to a separate SQL table, but CAML can’t query other data sources we have to store our read marks column with the item. The only recourse was to figure out how to save a SPListItem without firing events. Luckily Microsoft already provided this for us in the SPItemEventReiver base class, so all I had to do was poke around a bit and eventually I ended up with the SaveSPListItemWithoutFiringEvents method. It’s actually not a “cheat” just a creative use of a wrapper around the event handler to proxy calls into the SharePoint event manager. The calls to the event enablement functions are wrappers for some static calls Microsoft implemented in the base class, so it works out quite well.
This solved the problem of confusing other event handlers, and in a mostly read world (discussion groups, news groups, RSS feeds, etc), the system works fine. However some types of items that are very interactive, and when the item is updated by someone reading it (the control code updates the SPListItem), SharePoint will correctly notify any subsequent saves from the UI that their item is dirty. So if one user is actively editing, while others are reading, the editor will get conflict errors. To fix this I created the other set of cheats. I will only describe one, but you can look at them in the code. The core cheat is called AppendTextToSharePointNTEXTUserDataColumn and, as the name implies, it writes the read marks directly to the SQL table, bypassing the API. It uses the API to figure out where to put the data, and very careful SQL syntax for inserting and updating content, so it’s as well behaved as possible, but unlike the event manager, it does not simply reuse a stolen API, so it may be dangerous.
 
 I had originally thought I would have to validate the data in a synchronous OnUpdating event (just to reconcile updates from other users), but during testing, I discovered that SharePoint does a good job of only saving changed content fields. So it does not appear that saving the SPListItem overwrites the read mark column content, if the item context does not change the column content. If future testing reveals this to be a problem, we will have to reconcile the data in the event handler.

The project has just been updated to support some requested features. It is now possible to specifiy the color of the unread "highlight", simply put the HTML color code in the column defiinition. I also added some default images for unread marks if you like that view. In the source code you will fine a sample updated schema.xml file for an Announcement list that will incorporate the read/unread marking in the standard sharepoint web part summary view that is the default for list web part page displays. You ill have to do this manually, but i have tested most of the list types and they seem to work fine. The code for the actual list has not changed except to accomodate a few Safari issues that were brought to my attention. The release is just the WSP file so take the souce code down as well for notes and an overview.

Last edited Jul 13, 2016 at 4:51 PM by robginsburg, version 6