To read taxonomy field value(s) from a list item via CSOM can be quite cumbersome. Chris Domino explained those problems very detailed in his blog post.
I had the same problem that the CSOM API did not create the expected objects by itself but just returning a key value dictionary containing the taxonomy values. So I decided to write two extension methods for the ListItem class.
private const string ChildItems = "_Child_Items_";
private const string ObjectType = "_ObjectType_";
public static TaxonomyFieldValue GetTaxonomyFieldValue(this ListItem item, string internalFieldName)
{
if (item == null) throw new ArgumentNullException("item");
if (internalFieldName == null) throw new ArgumentNullException("internalFieldName");
if (!item.FieldValues.ContainsKey(internalFieldName))
{
throw new ArgumentException(string.Format("The field '{0}' does not exist.", internalFieldName), "internalFieldName");
}
var value = item[internalFieldName];
var taxonomyFieldValue = value as TaxonomyFieldValue;
if (taxonomyFieldValue != null)
{
return taxonomyFieldValue;
}
var dictionary = value as Dictionary<string, object>;
if (dictionary != null)
{
return ConvertDictionaryToTaxonomyFieldValue(dictionary);
}
throw new InvalidOperationException(
string.Format(
"Could not convert value of field '{0}' to a taxonomy vield value. Value is neither a TaxonomyFieldValue nor a Dictionary",
internalFieldName));
}
public static ReadOnlyCollection<TaxonomyFieldValue> GetTaxonomyFieldValueCollection(this ListItem item, string internalFieldName)
{
if (item == null) throw new ArgumentNullException("item");
if (internalFieldName == null) throw new ArgumentNullException("internalFieldName");
if (!item.FieldValues.ContainsKey(internalFieldName))
{
throw new ArgumentException(string.Format("The field '{0}' does not exist.", internalFieldName), "internalFieldName");
}
var value = item[internalFieldName];
var taxonomyFieldValueCollection = value as TaxonomyFieldValueCollection;
if (taxonomyFieldValueCollection != null)
{
return new ReadOnlyCollection<TaxonomyFieldValue>(taxonomyFieldValueCollection.ToList());
}
var dictionary = value as Dictionary<string, object>;
if (dictionary != null)
{
return new ReadOnlyCollection<TaxonomyFieldValue>(ConvertDictionaryToTaxonomyFieldValueCollection(dictionary));
}
throw new InvalidOperationException(string.Format(
"Could not convert value of field '{0}' to a taxonomy vield value. Value is neither a TaxonomyFieldValue nor a Dictionary",
internalFieldName));
}
private static TaxonomyFieldValue ConvertDictionaryToTaxonomyFieldValue(Dictionary<string, object> dictionary)
{
if (!dictionary.ContainsKey(ObjectType) || !dictionary[ObjectType].Equals("SP.Taxonomy.TaxonomyFieldValue"))
{
throw new InvalidOperationException("Dictionary value represents no TaxonomyFieldValue.");
}
return new TaxonomyFieldValue
{
Label = dictionary["Label"].ToString(),
TermGuid = dictionary["TermGuid"].ToString(),
WssId = int.Parse(dictionary["WssId"].ToString(), CultureInfo.InvariantCulture)
};
}
private static List<TaxonomyFieldValue> ConvertDictionaryToTaxonomyFieldValueCollection(Dictionary<string, object> dictionary)
{
if (!dictionary.ContainsKey(ObjectType) || !dictionary[ObjectType].Equals("SP.Taxonomy.TaxonomyFieldValueCollection"))
{
throw new InvalidOperationException("Dictionary value represents no TaxonomyFieldValueCollection.");
}
if (!dictionary.ContainsKey(ChildItems))
{
throw new InvalidOperationException(string.Format("Missing '{0}' key in TaxonomyFieldValueCollection field.", ChildItems));
}
var list = new List<TaxonomyFieldValue>();
foreach (var value in (object[])dictionary[ChildItems])
{
var childDictionary = (Dictionary<string, object>) value;
list.Add(ConvertDictionaryToTaxonomyFieldValue(childDictionary));
}
return list;
}