Monday, 14 December 2015

Property promotion and Programatically Copying documents with only required fields in SharePoint 2013.

Recently I was working on a requirement to copy documents between two site collections where the source and target document library had the same content type applied to them. The approach I took was to
- Get the source document library item
- Get the target folder where the document was to be copied
- Use the SPFolder.Files.Add() to copy the document.

Fairly simple ! The only thing I had to take care of was to copy only a specified set of field values (not all fields from content type) to the target file. (This was a part of the requirement !)

There is an overload of the ADD method that allows us to pass a Hashtable which will contain the fields that we want to copy over to the target file. So for example if I want to copy "Document Id" field of a document, I'll pass the property like this

Hashtable itemProperties = new Hashtable();
itemProperties.Add ("Document Id", "<VALUE>");

Now, though I passed only the required properties through a hashtable, all the field values of the content type were being copied. After a bit of head-scratching, I figured out that this scenario was not reproducible for a ".TXT" file but only for Microsoft Office files. This was because of SharePoint property promotion. What this basically does is when a document is added to a document library, the values of the fields in the list item for the document are added to the metadata properties of the document file and since the stream of the file was used to copy the document, the properties were getting transferred with it.

The property "ParserEnabled" of Web object allows SharePoint to know whether to retain all the properties when a file is copied/downloaded-uploaded.

So to copy only the required properties, you can disable ParserEnabled property of the web, copy the document and then set it back again

But you would not want to set the ParserEnabled property to false permanently so of course you would set it back to true in the FINALLY block of your code :)

Hope this helps !