Code Camp Wrap Up

This year’s code camp is a wrap! I’d like to thank my fellow organizers: Dan Attis, Sergey Barskiy, Mark Rowe, and Jim Wooley. It is such a pleasure to work with people who do what they say they will do! I especially want to thank Jim because he did all of his work knowing that he would not be able to attend the event, the speaker dinner, or the after party! Truly selfless.

We will have the speaker’s decks on the code camp web site as soon as possible. In the meantime, you can download my JavaScript deck here: http://www.elumenotion.com/Downloads/CC%202012%20Better%20JavaScript.pptx

Of course I would be very remiss if I forgot to thank the speakers, sponsors, and volunteers that made the event possible. Y’all are awesome!

 

 

–Doug

Correctly Provisioning Managed Metadata Columns

Last year I was brought in to help rescue a large and badly floundering project. The system in question made use of managed metadata in several areas and the original developers used Ari Bakker’s blog and code as their basis, specifically the code and in this excellent blog post. Ari began his journey with this excellent blog post from Wictor Wilén. Over time we had sporadic issues with upgrade scenarios and duplicate hidden note fields, but these were pretty low on the list of issues we needed to deal with before the system could go live (it was a real mess) and I never had the chance to dig in and figure it out.

Recently my friend and fellow MVP Dan Attis asked me to take a look at a similar issue he was facing with a sandbox solution. For whatever reason, the sandbox’s behavior was slightly different from the equivalent farm code. It had the same sort of problem I’d seen on the rescue project, but in the sandbox case it was worse as it prevented his affected features from activating. Together, Dan and I found the issue which was an error in Ari’s post. Before I get into that, having a look at the post in question is definitely worthwhile as what I have written here and my sample code is based upon his good work (which in turn is based on Wiktor’s), and I won’t be rehashing everything he wrote.

The Mistakes

Ari’s mistake comes with his step 3.

You should not do this. SharePoint will do it for you. If you do, SharePoint will create a duplicate with a different internal name in a farm solution and fail when you try to use an associated content type in a sandbox solution. Instead you need to provide enough information for SharePoint to create the required hidden note field as follows.

The Value attribute above will cause SharePoint to automatically provision a hidden note field with an ID of {2702cde3-3435-0227-be7b-e86d5f1250cc}.

Later in his post Ari writes about the creation of a Content Type that contains the metadata column and includes the hidden note field as one of the field references. You should not do this! Below is a sample content type inherits from the Document content type and includes the Color field shown above.

At this point my sample diverges from Ari’s because instead of using a list definition I use a ListInstance, a ContentTypeBinding, and a feature event receiver instead of a list definition. I do so because I think it’s easier, I am lazy, and I need the receiver anyway as my sample illustrates the use of metadata navigation in the resulting library. More on that later…

Timing is Everything

For my example to work I need to control the order of events so that:

  1. SharePoint provisions the Field and Content Type
  2. A feature event receiver connects the field to the correct term set
  3. The Content Type is bound to the list

If step 3 happens before step 2, the resulting list field(s) will not be connected to the term store. In Dan’s case this didn’t matter because in sandbox mode you have to wire up the metadata by hand as the required DLLs are not available in the sandbox.

The Sample

You can download the sample code from http://www.elumenotion.com/Downloads/MetadataSample.zip. It contains three features.

Visual Studio activates them in the order indicated above because of the way I’ve configured the package, but in real life I’d have a fourth feature to control the order of activation.

  • FieldsAndTypes includes the Field and ContentType elements shown in the screen shots above.
  • TermSetConfig creates a term set named Colors and connects the Color field to the new term set. This code is stolen borrowed directly from Ari and Wiktor with some minor changes and so I won’t cover it here.
  • SampleDocumentLibrary creates the sample library, binds my content type and then executes code to configure the metadata navigation settings for the new library.

The ListInstance and ContentTypeBinding look like this:

The feature event receiver does the following steps.

  1. Delete the original document content type from the library.
  2. Configure the metadata navigation settings.
  3. Configure the default view to display the Color column

public class SampleDocumentLibraryEventReceiver : SPFeatureReceiver

{

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWeb web = (SPWeb)properties.Feature.Parent;
SetupSampleDocumentLibrary(web);
}

private void SetupSampleDocumentLibrary(SPWeb web)
{
SPList docs = web.Lists["Library with Metadata"];

    docs.ContentTypes[0].Delete();

    var navSettings = MetadataNavigationSettings.GetMetadataNavigationSettings(docs);
navSettings.ClearConfiguredHierarchies();
navSettings.ClearConfiguredKeyFilters();
AddKeyFilter(docs, navSettings, "Color");
AddHierarchy(docs, navSettings, "Color");
MetadataNavigationSettings.SetMetadataNavigationSettings(docs, navSettings, true);

    docs.RootFolder.Update();
SPView view = docs.DefaultView;
view.ViewFields.DeleteAll();
view.ViewFields.Add("DocIcon");
view.ViewFields.Add("LinkFilename");
view.ViewFields.Add("Color");
view.Query = @"<OrderBy><FieldRef Name='FileLeafRef' Ascending='TRUE' /></OrderBy>";
view.Update();
}

private static void AddHierarchy(SPList matters, MetadataNavigationSettings navSettings, string fieldName)
{
MetadataNavigationHierarchy hierarchy = new MetadataNavigationHierarchy(matters.Fields[fieldName]);
navSettings.AddConfiguredHierarchy(hierarchy);
}

private static void AddKeyFilter(SPList matters, MetadataNavigationSettings navSettings, string fieldName)
{
MetadataNavigationKeyFilter filterNavigation = new MetadataNavigationKeyFilter(matters.Fields[fieldName]);
navSettings.AddConfiguredKeyFilter(filterNavigation);
}

 

Finally the screen shots below show the sample in action.

Adding a document


Metadata Navigation


 

Happy SharePointing!!!
–Doug

Author: Doug Ware

Atlanta Code Camp is this Weekend, Saturday May 19th

For the last few weeks the organizing committee for this year’s Atlanta Code Camp (including myself!) has been busily planning and organizing this year’s Atlanta Code Camp. This year’s event is once again on the campus of Southern Polytechnic State University in Marietta. You can read more and register for the event here: http://www.atlantacodecamp.org/default.aspx.

If you’re not familiar with code camps, they are free community‐focused events by and for the .NET developer community. The Atlanta Code Camp draws upon the expertise of local and regional developers, architects, and experts who come together to share their real world experiences, lessons learned, best practices, and general knowledge with other interested individuals.

This event is unique in that it is "for the community, by the community" and is free for all that desire to attend. In past years, the Atlanta Code Camp has provided free training and networking opportunities for 300 of the best, most motivated development professionals. With our larger facility, we’re expecting this year to be even bigger and better.

This is a free event and we provide lunch. I hope to see you there!

–Doug