Michel Barneveld
To unpathed waters, undreamed shores
How to create a custom DocumentIdProvider for SharePoint 2010 (including source code)

 

[4/26/2010] Updated with interface changes from beta2 to rtm

In SharePoint 2010 there is a new feature called the Document ID. When that feature is enabled, it will assign an unique ID and a permanent url to the document in a document library. Documents can be found using that Document ID, even if the document is moved to another location within the document library, site, or farm.

The default structure of the DocumentID is: <PrefixString>-<ListId>-<ListItemId>
Example: E2E4NK52YQC4-2-4

That prefix string is created as a unique string for every Site Collection. The first way to customize the DocumentID is to use the Document ID Settings page in Site Settings.
In this page you can change the prefix string:

 

But if that is not enough customization, there is also an other way: Your own DocumentIDProvider implementation.

Just derive your class from the abstract class Microsoft.Office.DocumentManagement.DocumentIdProvider and implement 1 property and 3 methods,

But before we take a look at the methods we need to implement, let's take a look how Document IDs work.

How does a Document ID work

When a document is added to a document library and the Document ID feature is enabled in that site collection, the event ItemAdded is trapped and the registered Document ID Provider is asked to generate a Document ID. This ID is then assigned to the DocumentID column. Note that the asynchronous event ItemAdded is used and not ItemAdding to be able to access metadata for the Item when assigning Document IDs. This page in the documentation explains more about the different events that are used: Document IDs and the DocID Service.

When you use a view that includes the DocumentID column or when you view the properties of the item, you will notice that the Document IDs are rendered as links to: _layouts/DocIdRedir.aspx

 

There is also a Document ID webpart to search for documents (The normal search also finds documents with Document IDs). That webpart also uses the DocIdRedir.aspx page.

If you want to add this webpart, it's in the Documents Category and not in the Search Category:

 

How does DocIdRedir.aspx work?

The DocumentID column is an indexed property of Search. So when your document is indexed it can be found by using the Search API. But the Out-of-the-box DocumentIdProvider does something smarter first.

Remember that the default structure of the DocumentId is: <Prefix>-<ListID>-<ListItemID>. So before asking SharePoint Search to find the document, it will first check the prefix if that is the prefix of the current Site Collection and if it is it can quite easy get the Item based on the ListID and ListItemID. If the item exists and it has the same DocumentID then the users is redirected to this document. If the document can't be found via this optimized way, then the Search API is used. If that also can't find the document then an error is shown.

Example of error message:

That is the behaviour of the Out-of-the-box DocumentIdProvider. Now we have enough information to look on how to custimize the provider.

 

Custom DocumentIdProvider

The generating of Document IDs can be custimized by creating a class that derives from Microsoft.Office.DocumentManagement.DocumentIdProvider

The definition of DocumentIdProvider:

namespace Microsoft.Office.DocumentManagement
{
  public abstract class DocumentIdProvider
  
{
   
protected DocumentIdProvider();
   
   
public abstract bool DoCustomSearchBeforeDefaultSearch { get; }

   
public abstract string GenerateDocumentId(SPListItem listItem);
   
public abstract string[] GetDocumentUrlsById(SPSite site, string documentId);
   
public abstract string GetSampleDocumentIdText(SPSite site);
  }
}

You have to implement the 3 abstract methods and 1 abstract property. But how are they meant to be used?


DoCustomSearchBeforeDefaultSearch

So what does this property do? Remember that the ootb provider first tries to find the document based on the ListId and ListItemId and if that doesn't give a result it will revert to using SharePoint Search. This boolean controls that behaviour. Notice that there is also a GetDocumentUrlsById method in this interface.

If you return true, then you let the DocIdRedir.aspx know that you want it to call the GetDocumentUrlsById first before calling Search. If you let this Property return false, you want to use SharePoint Search first, before using the GetDocumentUrlsById method. Note that it will only tries the 2nd search method when the first search method doesn't return a result!


GenerateDocumentId

This method is needed to generate the DocumentId. The SPListItem is passed as an argument in case you want to generate a Document ID based on the list item metadata. You have to return your DocumentId as a string.


GetDocumentUrlsById

This method is used to return the urls of the document based on a Document ID. This can be used as an alternative when the document isn't indexed yet and therefor the Search way didn't returned a result. Or if you have beter way to retrieve the document in the Site Collection.

If you don't want to return any urls, just return an empty string array.

     return new string[0];

If DoCustomSearchBeforeDefaultSearch was true, then returning the empty string array will signal the DocIdRedir.aspx to try it again with the SharePoint Search.
If DoCustomSearchBeforeDefaultSearch was false then the SharePoint Search was called first but didn't gave a result and the GetDocumentUrlsById was called. Returning an empty string array in that case will generate a message that the file could not be found.

An other possible scenario is that you set DoCustomSearchBeforeDefaultSearch to false and rely on the SharePoint Search. And if that can't find your document, you use the GetDocumentUrlsById to return a fixed url to a page that informs the user that the document can't be found (e.g. The document might not be indexed at this time if it was recently added.)

     

GetSampleDocumentIdText

This method is used to populate the Document ID webpart with an example.
   

 The text E2E4NK52YQC4-1-1 is returned by this method in above example.

 

 

Registering the provider?

So now that you have implemented your custom DocumentIdProvider, how do you get it registered to a Site Collection (or unregistered)?

I didn't find any STSADM or PowerShell command for that, but the class Microsoft.Office.DocumentManagement.DocumentId has 2 methods that we can use:

  public static void SetDefaultProvider(SPSite site);
  public static void SetProvider(SPSite site, DocumentIdProvider iProvider);

The method SetProvider will register your provider to SPSite and removing it is done by calling SetDefaultProvider.

  
A good way to call these methods is in the events of a Feature event receiver.

 

Example:

  public override void FeatureActivated(SPFeatureReceiverProperties properties)
  {
    
SPSite site = (SPSite)properties.Feature.Parent;
   
DocumentId.SetProvider(site, new GuidDocumentIdProvider()));
  }

 
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
  {
    
SPSite site = (SPSite)properties.Feature.Parent;
   
DocumentId.SetDefaultProvider(site);
  }

 

Once the custom provider is registered, you will not be allowed to change the prefix in the Document ID Settings page in Site Settings.Which is logical, since you are no longer using the OOTB DocumentIdProvider.

 

Example source code

I also uploaded an example implementation to the Files section. It includes a SharePoint 2010 project for Visual Studio 2010 (beta2). That project contains the Custom DocumentIdProvider called GuidDocumentIdProvider that uses GUIDs as Document IDs and a feature GuidDocumentIdFeature to enable and disable the GuidDocumentIdProvider.

Code can be found here: Custom DocumentIdProvider Example

When experimenting with this example, make sure you crawl your SharePoint site after adding documents, otherwise the documents can not be found by the DocIdRedir.aspx page.

 


Posted 12-05-2009 2:49 PM by Michel Barneveld
Filed under: , ,

Comments

Dutch Information Worker Team Blog wrote Unieke documentID's in SharePoint 2010
on 12-14-2009 9:42 PM

In SharePoint 2010 is er een mooie feature geintroduceerd; documentid's. Met documentid's wordt aan ieder

Marco wrote re: How to create a custom DocumentIdProvider for SharePoint 2010 (including source code)
on 02-09-2011 2:32 PM

The SPListItem is passed as an argument in case you want to generate a Document ID based on the list item metadata.

-----

Nope... This is the ugly thing... The Document ID is generated before you enter the Content Type Fields... Very bad design from MS here.

Louis wrote re: How to create a custom DocumentIdProvider for SharePoint 2010 (including source code)
on 02-22-2011 3:53 PM

@Marco - What do you mean by "before you enter the Content Type Fields"??

The listItem argument of GenerateDocumentId contains a fully usable SPListItem, with field values as entered in the New Item form. The Doc ID is generated *after* you click save on that form. What's the problem?

I have not validated if the item ID (not Doc ID) is assigned yet, or still zero (as in ItemAdding vs ItemAdded).

Neha wrote re: How to create a custom DocumentIdProvider for SharePoint 2010 (including source code)
on 03-09-2011 5:04 AM

This is half....

Online Win wrote re: How to create a custom DocumentIdProvider for SharePoint 2010 (including source code)
on 08-30-2011 2:20 PM

some interesting and helpful stuff - thank you!

SharePoint Tutorial wrote SharePoint Template - Document Center
on 10-17-2011 9:46 AM

SharePoint Template - Document Center

Florisz wrote re: How to create a custom DocumentIdProvider for SharePoint 2010 (including source code)
on 11-02-2011 7:22 AM

The essence of a document ID in a DMS is that it is just Unique. The last thing we want/need is a document ID that is build of a sort folder structure! (Site-list-listitem) Bad design in the root!

Pulithevan wrote re: How to create a custom DocumentIdProvider for SharePoint 2010 (including source code)
on 05-09-2012 1:22 PM

I am using custom document id provider. It is working fine. But when i reset the document id's for all documents by checking the check box in the document id settings page, the GUID is assigned to all the documents. My custom document id format is not coming. If i had documents with my custom id, those would be replaced by GUID? What do i need to do to get it work for reset also?  

Pulithevan wrote re: How to create a custom DocumentIdProvider for SharePoint 2010 (including source code)
on 05-09-2012 1:29 PM

I am using custom document id provider. Document id is generated as per my format given in the provider. But when i reset the document id's for all documents by using the check box available in the document id settings page, only GUID is assigned to all documents. So all documents in the site collection have only GUID as document id. My id format is not coming. Do i need to do anything to get it work or is it a default behaviour? I need to have the id with my format in all the documents even after doing reset. Pls someone help me on this!!

Amit Oberoi wrote re: How to create a custom DocumentIdProvider for SharePoint 2010 (including source code)
on 07-25-2012 8:54 AM

Hi, does anyone have an idea on why the document id provider runs fine when called from the server itself where it is installed, where as when we call the website that is using the same feature as on server from a workstation on lan, this never generates and stores a unique document id for that? My solution is for FARM level. If anyone could reply to this problem of mine as I am not able to understand this being a newbie to sharepoint then it would a great help to me.

Thanks!

Blog de Juan Carlos González en Geeks.MS wrote SharePoint: Como crear un proveedor personalizado para generar Documents ID!
on 08-31-2014 11:27 PM

Como sabéis, una de las características novedosas que incorporó SharePoint 2010 a nivel de ECM (Enterprise

Add a Comment

(required)  
(optional)
(required)  
Remember Me?

  Enter code:
Copyright © 2003 - 2009 Michel Barneveld
Powered by Community Server (Non-Commercial Edition), by Telligent Systems