Join SharePoint architects, developers, and other professionals on 28th April for the second Belgian ‘SharePoint Saturday’ event. SharePoint Saturday is an educational, informative & lively day filled with sessions from respected SharePoint professionals & MVPs, covering a wide variety of SharePoint-orientated topics. SharePoint Saturday is FREE, open to the public and is your local chance to immerse yourself in SharePoint!
SharePoint Saturday () is organised by BIWUG (), the Belux Information Worker User Group.
Extra details and registration information can be found here: http://bit.ly/spsbe2012.
See you there,
A SharePoint 2010 Sandboxed Solution that adds a Ribbon Button that recycles all items in a Document Library with a single mouse click.
I' have created this miniproject more as an academic exercise in creating a Ribbon Button than for real business value. It can come in handy for development environments sometimes.
Installation and activation
Download from here (Ventigrate Codeplex Repository)
Upload the WSP (sandbox solution) to the Site Collection Solution Gallery and activate it
Activate the Site Collection Feature
Final note
Some lessons learned and things worth noting:
- Use a Module to deploy resource files to a folder or library like the Style Library (Sandbox cannot access the Layouts folder)
- The Module will overwrite the existing resource files with a newer version, but will not delete them
- Working with ECMAScript seems to have no effect on resource or resource quota
- Use InPrivate Browsing for testing Ribbon development, this avoids caching of Ribbon resources
-
CustomAction.ScriptSrc points to the Layouts folder when using relative URLs. Use ~SiteCollection if you want to reference a resource in the Site Collection
Issue
Today I was troubleshooting a customer farm where Managed Metadata would remain empty in SharePoint, even though it was filled in correctly in the document’s Document Information Panel.
Digging through the internal XML structures of the DOCX and also the Content Type Schema and Field XML, I couldn’t find a reasonable explanation.
The library was configured with multiple Content Types, but the issue occurred only on some of them. It appeared that for those Content Types, the Managed Metadata field was Optional, not Required.
I tried reproducing that configuration in a new document library but there everything kept working, so the issue had to be with the existing library.
Further analysis, comparison and reflection showed that the problematic library was missing some Taxonomy-related Event Receivers.
There appear to be four (4) Taxonomy Event Receivers:
-
TaxonomyItemSynchronousAddedEventReceiver (ItemAdding) and TaxonomyItemUpdatingEventReceiver (ItemUpdating) are added when a Managed Metadata field is added to the List
-
TaxonomyItemAddedAsyncEventReceiver (ItemAdded) and TaxonomyItemUpdatedEventReceiver (ItemUpdated) are added when “Metadata Publishing” is enabled in the List Settings
The problematic library at the customer was lacking the first set of Event Receivers, which are responsible for syncing the hidden field.
Fix
I’ve written a one-off script (Console App) that loops all lists with a Managed Metadata field on all sites in the site collection and ensures the Taxonomy event receivers. That code was taken directly from TaxonomyField.AddEventReceiverIfNotExists.
using System; using System.IO; using System.Text; using System.Windows.Forms; using Microsoft.SharePoint; using Microsoft.SharePoint.Taxonomy; class Taxonomy_Fix { public static StringBuilder sb = new StringBuilder(); public static string nl = "\r\n"; public static string url = "http://intranet"; public static void FIXALL() { using (SPSite site = new SPSite(url)) { foreach (SPWeb web in site.AllWebs) { FixTaxonomyReceiverOnWebLists(web); web.Close(); } } File.AppendAllText(String.Format("c:\\{0:HH_mm_ss}.txt", DateTime.Now), sb.ToString()); MessageBox.Show(sb.ToString()); } private static void FixTaxonomyReceiverOnWebLists(SPWeb web) { for (int i = 0; i < web.Lists.Count; i++) { SPList list = web.Lists[i]; if (HasTaxonomyField(list)) { sb.AppendFormat("{0}{1} has Taxonomy Field{2}", url, list.RootFolder.ServerRelativeUrl, nl); EnsureTaxonomyHandlers(list); } } } private static bool HasTaxonomyField(SPList list) { bool result = false; foreach (SPField field in list.Fields) { if (field is TaxonomyField) { result = true; break; } } return result; } private static void EnsureTaxonomyHandlers(SPList list) { AddEventReceiverIfNotExists(list.EventReceivers, SPEventReceiverType.ItemAdding, typeof(TaxonomyField).Assembly.FullName, "Microsoft.SharePoint.Taxonomy.TaxonomyItemEventReceiver", "TaxonomyItemSynchronousAddedEventReceiver", SPEventReceiverSynchronization.Synchronous); AddEventReceiverIfNotExists(list.EventReceivers, SPEventReceiverType.ItemUpdating, typeof(TaxonomyField).Assembly.FullName, "Microsoft.SharePoint.Taxonomy.TaxonomyItemEventReceiver", "TaxonomyItemUpdatingEventReceiver", SPEventReceiverSynchronization.Synchronous); } private static void AddEventReceiverIfNotExists(SPEventReceiverDefinitionCollection eventReceiverCollection, SPEventReceiverType type, string assembly, string className, string receiverName, SPEventReceiverSynchronization sync) { if (eventReceiverCollection == null) { throw new ArgumentNullException("eventReceiverCollection"); } if (string.IsNullOrEmpty(assembly)) { throw new ArgumentNullException("Valid assembly name required"); } foreach (SPEventReceiverDefinition erd in eventReceiverCollection) { if (erd.Assembly == assembly && className == erd.Class && type == erd.Type && erd.Synchronization == sync) { sb.AppendFormat("\t>> no action required{0}", nl); return; } } SPEventReceiverDefinition erd2 = eventReceiverCollection.Add(); erd2.Name = receiverName; erd2.Type = type; erd2.Assembly = assembly; erd2.Class = className; erd2.Synchronization = sync; erd2.Update(); sb.AppendFormat("\t>> Added TaxonomyEvent Receiver{0}", nl); } }
Disclaimer: not responsible for this code. Run at own risk. Feel free to adapt or improve as desired or required.
Conclusion
I can’t really explain why only some Content Types were affected. I’m guessing the Optional/Required setting of the Managed Metadata field is involved somehow, but I didn’t really confirm that through testing.
Also not sure why the Event Receivers were missing in the first place. It could be because some “questionable” actions happened during the setup of the site, but it could as well be a bug in SharePoint 2010 RTM or later.