Pnp & remote provisioning : how to enable metadata navigation for a list or library via xml template?
Question
it's me again.
Going deeper and deeper into PnP and remote provisioning is like a roller coaster experience. We can do so much things ! And yet, there is like no real formal documentation.
What i want :
Well, for today, my question is quite simple : Via my xml template, how do I set up my Library settings ? And more particularly, how do i set up metadata navigation (aka key filters) for my Library ?
What i did :
For the moment, i have two things.
- i've added the Web Feature in my Site Creation's xml template. Using this code below :
<
<pnp:Features> <pnp:WebFeatures><pnp:Feature ID="7201d6a4-a5d3-49a1-8c19-19c4bac6e668" Deactivate="false" Description="Metadata Navigation and Filtering (MetaDataNav) site feature" /></pnp:WebFeatures></pnp:Features>
- I've created my Document Library, enabling ContentTypes etc... like this :
<
<pnp:ListInstance Title="Documents projet"
Description="Documents partagées entre les acteurs du projet (ASI et client)"
TemplateType="101"
Url="documentprojet"
EnableVersioning="true"
EnableMinorVersions="true"
MinorVersionLimit="20"
MaxVersionLimit="100"
DraftVersionVisibility="0"
ContentTypesEnabled="true"
RemoveExistingContentTypes="true"
EnableFolderCreation="true">
<pnp:ContentTypeBindings>
<pnp:ContentTypeBinding ContentTypeID="0x010100BBD2E6E36069334ABFD4717B8C2FA4D9" Default="true" />
<pnp:ContentTypeBinding ContentTypeID="0x010100BBD2E6E36069334ABFD4717B8C2FA4D901"/>
<pnp:ContentTypeBinding ContentTypeID="0x010100BBD2E6E36069334ABFD4717B8C2FA4D902"/>
</pnp:ContentTypeBindings>
<pnp:FieldDefaults>
<pnp:FieldDefault FieldName="EtatValidation">Brouillon</pnp:FieldDefault>
<pnp:FieldDefault FieldName="EtatValidationCR">A valider</pnp:FieldDefault>
<pnp:FieldDefault FieldName="NumeroContrat">{parameter:NumContrat}</pnp:FieldDefault>
<pnp:FieldDefault FieldName="Client">{parameter:Client}</pnp:FieldDefault>
<pnp:FieldDefault FieldName="NomProjet">{parameter:Projet}</pnp:FieldDefault>
</pnp:FieldDefaults>
</pnp:ListInstance>
But i don't see anywhere any settings, any xml attriubte talking about metadata navigation. Is it already implemented or not ?
So, do you know how i should write my Library Creation xml template to set up my Metadata Navigation setting?
Thanks a lot for your help. have a nice day !
Solution
In CSOM and hence in PnP guidance, there is no equivalent to MetadataNavigationSettings
that we find in the Server Object Model 2013.
But there is a hack available which via property bag using CSOM. By setting the property bag value, you would be able to achieve the Metadata navigation setting.
Try the below code:
private static void AddMetadataNavigationToDocLib()
{
ClientContext ctx = new ClientContext("https://SiteUrl");
var rootWeb = ctx.Site.RootWeb;
List docLib = ctx.Web.Lists.GetByTitle("Documents");
ctx.Load(rootWeb, p => p.AvailableFields);
ctx.Load(docLib, p => p.RootFolder, p => p.RootFolder.Properties);
ctx.ExecuteQuery();
if (rootWeb.AvailableFields.Any(p => p.InternalName.Equals("MetadataFieldName")))
{
var field = rootWeb.Fields.GetByInternalNameOrTitle("MetadataFieldName");
ctx.Load(field, p => p.Id, p => p.InternalName, p => p.TypeAsString);
ctx.ExecuteQuery();
var sb = new StringBuilder();
sb.Append("<MetadataNavigationSettings SchemaVersion='1' IsEnabled='True' AutoIndex='True'>");
sb.Append("<NavigationHierarchies><FolderHierarchy HideFoldersNode='False' />");
sb.AppendFormat("<MetadataField FieldID='{0}' FieldType='{1}' CachedName='{2}' CachedDisplayName='{3}' />", field.Id, field.TypeAsString, field.InternalName, field.InternalName);
sb.Append("</NavigationHierarchies><KeyFilters /></MetadataNavigationSettings>");
docLib.RootFolder.Properties["client_MOSS_MetadataNavigationSettings"] = sb.ToString();
docLib.RootFolder.Update();
docLib.Update();
ctx.ExecuteQuery();
}
}
Reference - Activating Document Lib Tree navigation using CSOM
MetadataNavigationSettings in Server object model 2013
Edit 2 - adding multiple fields as filters
private static void AddMetadataNavigationToDocLib()
{
ClientContext ctx = new ClientContext("https://SiteUrl");
var rootWeb = ctx.Site.RootWeb;
List docLib = ctx.Web.Lists.GetByTitle("Documents");
ctx.Load(rootWeb, p => p.AvailableFields);
ctx.Load(docLib, p => p.RootFolder, p => p.RootFolder.Properties);
ctx.ExecuteQuery();
if (rootWeb.AvailableFields.Any(p => p.InternalName.Equals("MetadataFieldName")) && rootWeb.AvailableFields.Any(p => p.InternalName.Equals("MetadataFieldName2")) && rootWeb.AvailableFields.Any(p => p.InternalName.Equals("MetadataFieldName3")))
{
var field = rootWeb.Fields.GetByInternalNameOrTitle("MetadataFieldName");
var field2 = rootWeb.Fields.GetByInternalNameOrTitle("MetadataFieldName2");
var field3 = rootWeb.Fields.GetByInternalNameOrTitle("MetadataFieldName3");
ctx.Load(field, p => p.Id, p => p.InternalName, p => p.TypeAsString);
ctx.Load(field2, p => p.Id, p => p.InternalName, p => p.TypeAsString);
ctx.Load(field3, p => p.Id, p => p.InternalName, p => p.TypeAsString);
ctx.ExecuteQuery();
var sb = new StringBuilder();
sb.Append("<MetadataNavigationSettings SchemaVersion='1' IsEnabled='True' AutoIndex='True'>");
sb.Append("<NavigationHierarchies><FolderHierarchy HideFoldersNode='False' />");
sb.AppendFormat("<MetadataField FieldID='{0}' FieldType='{1}' CachedName='{2}' CachedDisplayName='{3}' />", field.Id, field.TypeAsString, field.InternalName, field.InternalName);
sb.AppendFormat("<MetadataField FieldID='{0}' FieldType='{1}' CachedName='{2}' CachedDisplayName='{3}' />", field2.Id, field2.TypeAsString, field2.InternalName, field2.InternalName);
sb.AppendFormat("<MetadataField FieldID='{0}' FieldType='{1}' CachedName='{2}' CachedDisplayName='{3}' />", field3.Id, field3.TypeAsString, field3.InternalName, field3.InternalName);
sb.Append("</NavigationHierarchies><KeyFilters /></MetadataNavigationSettings>");
docLib.RootFolder.Properties["client_MOSS_MetadataNavigationSettings"] = sb.ToString();
docLib.RootFolder.Update();
docLib.Update();
ctx.ExecuteQuery();
}
}