Recently I started at a new company doing in-house work. The environment is a bit different than that to which I’m accustomed by its large reliance on 3rd party utilities and solutions. While these are great for companies lacking in development staff, many of these solutions are overly generic and can be frustrating to users who are looking for a more integrated experience.
Enter me and my first project.
In my current environment, just as in every other environment I’ve seen, we have users who use and love their file shares. These bastions of untamed digital wilderness have been the bane of many an IT person but their existence continues. To help mitigate some of the drawbacks of these audit-free, backup-less storage areas, Bamboo created a product which synchronizes file share content with a SharePoint document library. The solution uses a timer job to occasionally crawl the share looking for files and folders that have been added/changed and comparing against the files it has in the SharePoint library to see if anything has been deleted. The library is kept in sync (though with the option of archiving deleted items to soften the blow of those occasional accidental share deletes) and each item has a status which reflects the synchronization type.
Without getting too detailed about the product itself (you can easily look up the marketing material) I will explain our need. The custom document library that is created from this product contains a content type (BambooFileShareLibrary) with very few fields. Our users wanted the ability to have additional fields associated with items in the list. This is pretty straight forward – anyone could just add those fields to the list and be done with it.
This wasn’t an ideal solution. Instead it was decided we should have some sort of automatic way of adding the fields. When the team lead contacted Bamboo to ask about how we could add the fields to the default type, Bamboo suggested creating a child content type and writing an event receiver to change items’ content types to the new child when they were added to the list. This is the approach my predecessor took.
Needless to say the approach was flawed and, as written, didn’t work. I took a little time to explore and found the idea of the child content type was a solid one but changing the content type using an event receiver was posing a bit of a challenge. Then I think I stumbled on the problem: the Bamboo content type was set as the default for the list. When new items were uploaded by the timer job, they were automatically given this type. When the event receiver fired and attempted to change it to a child type and failed, this was either due to my code just being wrong or was actually possibly a bug in SharePoint which compared the existing content type with the new content type and was getting the result they were the same. My hunch is the comparison was not direct ID compares.
When I switched the default content type to our custom, child type, new items added to the list through the timer job were given this content type directly without the need for the event receiver at all!
Working from this observation the entire project became a lot cleaner and could even be done through the UI though I went ahead and created a feature for the custom content type for better test ability between environments.
The final solution was to create a content type in the usual way: site scoped feature, elements file with the field definitions, content type definition as a child of the Bamboo File Share Library content type with the fieldref elements* and that’s it.
*For some reason a couple text fields were getting Hidden=true by default. I added Hidden=false to all my fieldrefs and the problem disappeared.
To deploy, add the WSP to the solution store, deploy it and activate it in the site collection features. Go to a File Share Library you’ve created, into the list settings and Advanced Settings. Enable management of content types. Go back to the list settings and add existing site content type to add your new child content type. Change the order to make it the default. Go back to Advanced Settings and disable the management of content types.
Now when you sync the list, new items will be the expected child type. Also as expected, creating a new folder (only option under New) or uploading an item result in the user being prompted with the new fields you’ve specified in addition to the fields required by the parent content type.
To create a content type as a child of another, you’ll need the Content Type ID. I used the SharePoint Manager utility to examine the File Share Library instance I was using to see how it worked to figure out the solution above. You can get the id by examining the URL when browsing the content type through the UI. Use this as the ID of your content type appended with 2 zeros, “00” plus a new GUID with the curly braces and minus signs removed.
Bamboo File Share Library: 0x010100887202D2472D4F8FB67C45E910A6B56D004B1680454252BF4999F5E1FC07D0A7B6
Example Child Content Type: 0x010100887202D2472D4F8FB67C45E910A6B56D004B1680454252BF4999F5E1FC07D0A7B600541485110E2F4793B6E2452B6451E5AC
If your environment is using this handy utility to help wean users from the evils of file shares, this tip might help show them the usefulness of going straight to SharePoint for their needs.