Introduction

SharePoint 2013 introduces a new model on how Site Collections are upgraded using the new Deferred Site Collection Upgrade. To keep it simple it means that SharePoint 2013 can run a Site Collection in either 2010 mode or 2013 mode, and SharePoint 2013 contains a lot of the SharePoint 2010 artifacts (JS files, Features, Site Definitions) to handle this. When you’re doing a content database attach to upgrade from 2010 to 2013, only the database schema is upgraded and not the actual sites (by default). The actual Site Collection upgrade is done by the Site Collection administrator when they feel that they are ready to do that and have verified the functionality of SharePoint 2013 (or you force them to upgrade anyways). But, the Site Collection admin might have to upgrade sooner than expected for some sites.

Upgrade troubles

This post is all about what has happened to us when our Office 365 SharePoint Online (SPO) tenant had been upgraded (and right now the Site Collection upgrade is disabled for us so we can’t do anything about it). The limitations of customizations in the 2010 version of SPO was very limited (to be kind) and we embraced JavaScript (which people have despised for a decade and now suddenly think is manna from heaven). We also leveraged Managed Metadata in a lot of lists, libraries and sites. We’ve built Web Parts using JavaScript CSOM to render information and also .NET CSOM stuff running in Windows Azure doing background work. Once our tenant was upgraded to 2013 all of the customizations using Managed Metadata stopped to work…

JSOM sample with Managed Metadata

I will show you one example of what works in SharePoint 2010 and what does not work in SharePoint 2013 when you’re site is running in 2010 compatibility mode.

Assume we have a simple list with two columns; Title and Color, where Color is a Managed Metadata Field. To render this list using JSOM we could use code like this in a Web Part or Content Editor or whatever.

var products;
function loadProducts() {
	document.getElementById('area').innerHTML = 'Loading...';
	var context = new SP.ClientContext.get_current();
	var web = context.get_web();
	var list = web.get_lists().getByTitle('TestList');
	products = list.getItems('');
	context.load(products, 'Include (Title, Color)');
	
	context.executeQueryAsync(function() {
		var collection = products.getEnumerator();
		var html = '<table>'
		while(collection.moveNext()) {
			var product = collection.get_current();
			html +='<tr><td>'
			html += product.get_item('Title');
			html += '</td><td>'
			html += product.get_item('Color').split('|')[0];
			html += '</td></tr>'			
		}
		html += '</table>'
		document.getElementById('area').innerHTML = html;
	}, function() {
		document.getElementById('area').innerHTML = 'An error occurred';
	});
}
ExecuteOrDelayUntilScriptLoaded(loadProducts, 'sp.js');

As you can see a very simple approach. We’re reading all the items from the list and rendering them as a table, and this html table is finally inserted into a div (with id = area in the example above). This should look something like this when rendered:

JSOM Rendering in SharePoint 2010

The key here is that Managed Metadata in 2010 JSOM is returned as a string object (2010 .NET CSOM does that as well). This string object is a concatenation of the Term, the pipe character (|) and the term id. So in the code sample above I just split on the pipe character and take the first part. There was no other decent way to do this in SharePoint 2010 and I’ve seen a lot of similar approaches.

Same code running in SharePoint 2013 on a SharePoint 2010 mode site

If we now take this site collection and move it to SharePoint 2013 or recreate the solution on a 2010 mode site in SharePoint 2013. Then we run the same script, then this is what we’ll see, something goes wrong…

Failed JSOM Rendering

You might also see a JavaScript error, depending on your web browser configuration. Of course proper error handling could show something even more meaningful!

JSOM Runtime exception

Something is not working here anymore!

What really happens is that the CSOM client service do not return a string object for Managed Metadata but instead a properly typed TaxonomyFieldValue. But that type (SP.Taxonomy.TaxonomyFieldValue) does not exist in the 2010 JSOM. Remember I said that SharePoint 2013 uses the old 2010 JavaScripts when running in 2010 compatibility mode. Unfortunately there is no workaround, unless we roll our own SP.Taxonomy.TaxonomyFieldValue class (but that’s for another JS whizkid to fix, just a quick tip to save you the trouble – you cannot just add the 2013 SP.Taxonomy,js to your solution).

So why is this so then?

If we take a closer look at what is transferred over the wire we can see that when running on SharePoint 2010 the managed metadata is transferred as strings:

Fiddler trace on SharePoint 2010

But on SharePoint 2013 it is typed as a TaxonomyFieldValue object:

Fiddler trace on SharePoint 2013

It’s a bit of a shame, since the server is actually aware of that we’re running the 2010 (14) mode client components! (SchemaVersion is what we sent from the CSOM and LibraryVersion is the library used on the server side)

Fiddler trace on SharePoint 2013

I do really hope that the SharePoint team think about this for future releases – respect the actual schema used/sent by the Client Object Model!

Of course, this JavaScript solution will not work as-is when upgrading the Site Collection to 2013 mode. That is expected and that’s what the Evaluation sites are for.

What about .NET CSOM?

We have a similar issue in .NET CSOM, even though we don’t get a SharePoint CSOM runtime exception. Instead of returning a string object you will get back a Dictionary with Objects as values – but if you’re code is expecting a string you still get the exception. So in 99% of the cases it will fail here as well.

Nothing exciting here, move along…

Summary

Deferred Site Collection update might be a good idea and you might think that your customizations will work pretty well even after an upgrade to SharePoint 2013, just as long as you don’t update your actual Site Collections to 2013. But you’ve just seen that this is not the case.

Happy easter!