Tuesday 29 January 2013

SharePoint Content Organiser and Custom Routing

I recently received a request to spend some time reviewing whether or not Content Organiser Routing could be extended and customised.

The request came out of a problem encountered by one of our consultants when he set up a Content Organiser Rule which routed a document to a separate Site Collection. The destination Site Collection then had its own Content Organiser rules to add a document into a specific library existing in the site and implementing a folder structure based on the metadata included with the document. The folder structure would pre-exist and be set up using a custom Content Type and pre-populated metadata which the document, when it was added into the folder, would inherit.

This worked fine when a folder matching the metadata in the document already existed, however, if the folder did not already exist, despite setting the Content Organiser rule to create a new folder, SharePoint displayed a strange "security validation time out". After a little digging, I founder references to a "security validation time out" error from Microsoft who had already resolved the problem in the form of a requestable Hotfix (KB2596584 - http://support.microsoft.com/kb/2596584) which as far as I could see did not form part of SharePoint SP1 (which is what the server was running). I requested, downloaded and installed the Hotfix (after snapshotting our VMware Server) and it resolved the issue and functionally the system was working as expected.
 
That was great, so from a client perspective, there was no more odd message that didn't mean much, and not only that but the Content Organiser rule now appeared to working properly.
 
However, based on our requirement it was necessary that the folder that was created automatically would have to use our own custom Content Type, not the standard Folder Content Type. Despite removing the New Folder options from the destination library and making the custom Content Type available, the Content Organiser would always create any new folder using the standard Folder Content Type, which was pretty much what I expected. So, I started looking into Custom Routers.
 
A Custom Router can be created using the simple Interface ICustomRouter. It implements a single method OnSubmitFile in which you can do some additional or alternate processing before handing back to the EcmDocumentRouter. Registering a Custom Router is straight-forwards. I used a very simple Console Application as I was only researching the issue, but ideally this would be a Web or Site Feature that registers the Custom Router on activation (and removes it on deactivation).

Once the Custom Router is registered (using the EcmDocumentRoutingWeb.AddCustomRouter method) it becomes available through the UI when you add or edit a Content Organiser Rule:



 
When you register the Custom Router the first parameter is the Name - this is what appears in the dropdown above. Once this is set up on the Content Organiser Rule it means that the Content Organiser does its normal processing up to a point and then makes the call into the Custom Router. It appears from what I've seen that the call is made to the Custom Router just prior to actually saving the file to its final destination, therefore, any processing that may be required to make this happen would have already been done, i.e. creating a new folder, which I'll come back to in a moment.

The Custom Router's OnSubmitFile method call can return one of two CustomRouterResult options: SuccessContinueProcess and SuccessCancelFurtherProcessing (obviously no room for failure here)...

As I just mentioned, if you are setting a rule up to create a folder if it doesn't exist (which we are in our scenario), regardless of which result you return, the folder will always get created. The difference in result types is more apparent from what happens to the routed file. Returning SuccessContinueProcessing does exactly what it says, it carries on after the Custom Router code and performs the standard and expected behaviour, i.e. routes the document according to what rules you have and actually performs the save to the final destination. SuccessCancelFurtherProcessing, however, doesn't process any further, as the name suggests, therefore, as you can see in the MSDN example, it useful if you are going to handle what happens yourself and you don't need the out-of-the-box routing to do anything. What I would say is that returning SuccessCancelFurtherProcessing will mean that the file is lost: I returned this value during my testing and the routed file disappeared from the Drop-Off Library as expected and never appeared in the destination library which only makes me think that this option is really only useful if you are going to implement the saving of the file yourself.

Back to our scenario, I was able to use the Custom Router to reset the metadata and Content Type of the already created folder (as we get a reference to this in the OnSubmitFile method) which fitted what we were looking for. I had a quick try and yes, it worked, however, there is a caveat. What I expected was that items subsequently added into the updated folder would inherit the metadata set on the folder. In my short trial of this, it didn't work that way, so I suspect I'm not setting something or some configuration is missing, so just be aware that it may be an issue.

Hopefully this has been of some use.