FTC to CAM – Setting indexed property bag keys using CSOM

Related on to my previous post on storing metadata values for sites using CSOM, I got quite few questions on how would we then use these property bag keys or their values in aggregations. In general with SP2013 easiest solution would be probably use search to crawl the property bag values and then use those as filters for the listing the sites based on end user selection.

Steve Peschka has explained in his blog post how we can set property bag key to be indexed using server side code, but this SPWeb.IndexedPropertyKeys property is not available for CSOM, so you can’t directly use same pattern to set the property bag values to be indexed and therefore we’ll need to look for alternative route for achieving the same end result, like in so many times with CSOM or CAM model in general.

After however analysing slightly more detailed how IndexPropertyKeys property works (using ILSpy), we can come up with solution also using CSOM. Server side implementation works in a way that property bag values which are set to be index by search are actually stored to property bag as well, using key ‘vti_indexedpropertykeys’. This list is encoded and property bag entries are separated with pipe character. This means that as long as we use exact same format in our provider hosted app and store the list to host web in similar ways as using server side code, we are fine.

To demonstrate this, I have updated the reference code which was also shared in previous blog as follows.

1. We need to have the function, which formats our list of property bag keys to proper format, which is then stored to SPWeb.Properties using CSOM


 /// <summary>
/// Used to convert the list of property keys is required format for listing keys to be index
/// </summary>
/// <param name="keys">list of keys to set to be searchable</param>
/// <returns>string formatted list of keys in proper format</returns>
internal static string GetEncodedValueForSearchIndexProperty(List<string> keys)
{
    StringBuilder stringBuilder = new StringBuilder();
    foreach (string current in keys)
    {
        stringBuilder.Append(Convert.ToBase64String(Encoding.Unicode.GetBytes(current)));
        stringBuilder.Append('|');
    }
    return stringBuilder.ToString();
}
 
 
 

2. Few additional lines to actually get the keys to be stored and to save it to property bag using ‘vti_indexedpropertykeys’ key.


 // Confirm that both property bag values are indexed by search
List<string> keys = new List<string>();
keys.Add(DeployManager.ProjectCodeBagID);
keys.Add(DeployManager.ProjectPhaseBagID);
SetPropertyValue(clientContext, props, "vti_indexedpropertykeys", GetEncodedValueForSearchIndexProperty(keys));

That’s it and now those custom properties stored in the property bag of the site (spweb) are being indexed by search and we can build search driven content based on the information entered to these property bag entries. This solution obviously works in both on-premises and in cloud.

Disclaimer. Since this functionality is not currently exposed as public property in CSOM, there is a risk that implementation might be changing in future. This is valid, but relative small risk, but you should be aware of it. I’ll be personally using this pattern as well with few of my customers related on the FTC to CAM migration work.

References

Here’s just the collected list of referenced locations and materials