Generating Unique IDs for Folders in SharePoint Document Library using Document ID Service

Document Id Service that comes with SharePoint Out-of-the-box provides neat feature to assign Unique Document Ids to Documents in SharePoint Libraries, but obviously only works with mmmm Documents! What if you had do something similar for Folders also and stick to Of-the-box format like {Some-Prefix}-{Id}-{ItemId} without worrying about where each part of Id is coming from where.

Here’s a quick How to and PoC Code:

When you set up Document ID Service on a site collection, following two columns are added to the Document Libraries:

_dlc_DocId and _dlc_DocIdUrl

_dlc_DocId just stores the display text of the Document ID and _dls_DocIdUrl stores a Url which is in format of
{SPWeb Url}/_layouts/15/DocIdRedir.aspx?ID={DocId}

In SharePoint this columns are also available to really any item in he Document Library (see the screen below) and we are going to hijack above two columns and populate Document Ids for Folders.

FolderId-1

So now how do we actually generate the Id, one option I initially thought was to provide a custom DocumentId Provider and also generate a Id for Folder Item but following method on DocumentProvider never fires for folders.

public abstract string GenerateDocumentId(SPListItem listItem);

So we would need to provide our own Event receiver to handle the generation of IDs for Folder Id fair which is fair enough but goal is to stick to absolutely with the Id which Out-of-the-box generates, so I went digging to work out how out-of-the-box does it and thanks to dotPeek I found OobProvider (Gotta love the name!) and to my delight it was public so I am going to use it, albeit it’s in an Internal namespace

OOB Document ID Provider

Its simply now matter of calling GenerrateDocumentId method of OobProvider from your event receiver for Folder Items and updating two OOB columns with appropriate values:

 OobProvider p = new OobProvider();
string folderUId = p.GenerateDocumentId(properties.ListItem);
item["_dlc_DocId"] = folderUId;
item["_dlc_DocIdUrl"] = new SPFieldUrlValue()
{
Url = string.Format("/_layouts/15/DocIdRedir.aspx?ID={0}", folderUId),
Description = folderUId
};
item.SystemUpdate();

Sample PoC to generate Folder Ids using above discussed approach can be found at Git Hub SharePoint Folder Id Repository. There are few things the PoC Provides:

  • Site collection level Folder Id Feature, Feature adds a Sync Item Added Event Receivers to Document Library and it has dependency on OOB Document Id Service feature so you want be able to activate Folder ID feature without the OOB Document ID feature in place.
  • Provides a Pausable timer job to reset the Folder Ids or set the Folder Ids of existing folders in a site collection, TimerJob is based on something similar to OOB timer job and makes use of  SPWorkItemJobDefinition and rather unknown TimerJobUtility (which basically inherits from ContentIterator), this ensures that Timerjob will work with Large lists (I have tested it with a document library containing ~8k items out of which ~3K where folders). Use of TimerJobUtlity probably warrants it’s own Post because it provides very cool functionality which was hidden to me until now!
  • An application page is provided via which a re-assignment of folder id can be triggered which I imagine will be useful in a scenario where Document Id  prefix for the site collection is changed and there is a need to re-generate FodlerIds based on that. (Please note there is no custom action to get to  the page, just go to http://siteCollection/_layouts/15/SharePoint.FolderIds/FolderIds.aspx).
  • It uses exactly same approach to OOB to work out which Document Provider to use in case a custom Document Provider is Set for a Site Collection.