After some experimenting, I found that the only two columns you need to set are the ID and Type
ID needs to have 61cbb965-1e04-4273-b658-eedaa662f48d set as it’s value
Type needs to have TargetTo set as it’s value
You still need to provide values for Name, DisplayName, StaticName, but they can be whatever you want.
Don’t like the name Target Audiences then you can change it to something else. The great thing is, it can still be turned off through the List or Library settings page.
To enable Audinence targeting using PnP PowerShell it’s as simple as running this script.
Metadata navigation and per-location views are an little known, but powerful way of making lists more useful.
It allows you to assign a default view and others views to a folder, content type or field. My need was to allow users to navigate using a Taxonomy field. Dependent on the selected field, I would like to show different fields using a view.
The first part is to add the Metadata navigation.
This is done by creating a hierarchy using MetadataNavigationHierarchy
1 2 3 4 5 6 7 8 9
var list = SPContext.Current.Web.Lists.TryGetList("MyList"); var field = list .Fields.TryGetFieldByStaticName("MyField"); var settings = MetadataNavigationSettings.GetMetadataNavigationSettings(list); var hierarchy = settings.FindConfiguredHierarchy(field.Id);
if (hierarchy == null) { hierarchy = new MetadataNavigationHierarchy(field); settings.AddConfiguredHierarchy(hierarchy); }
The hard part is adding the settings for the per location views.
This can only be done by injecting XML into the settings XML. MetadataNavigationSettings is a wrapper class around an XML snippet that is stored in a hidden property of the root folder of the list.
Have a look at SPList.RootFolder.Properties["client_MOSS_MetadataNavigationSettings"]
The XML Schema is as follows. Haven’t found anything documenting this schema on MSDN yet, so this is just taken from my configuration of my list, so may differ on yours
The part I’m interested in here is the ViewSettings and View tag. The UniqueId attribute relates to the GUID of the selected Term GUID. So this will show the views defined using the View tag when the Term is selected in the Metadata navigation.
If a View tag is added with 0 index this will be used as the default view when the term is selected, all other positive numbers will be shown in the order defined as other available views for that Term. Any negatives will not be available (You don’t need to add them)
I used the following code to add these nodes programmaticallty using XLinq
var list = SPContext.Current.Web.Lists.TryGetList("MyList"); var view = list.Views.Cast().SingleOrDefault(v => v.Title == "MyView"); var session = new TaxonomySession(SPContext.Current.Site); var field = list.Fields.TryGetFieldByStaticName("MyField"); var term = session.GetTerm("a96cea49-ef78-4bfa-8a69-2c49071155fb"); var settings = MetadataNavigationSettings.GetMetadataNavigationSettings(list); var doc = XDocument.Parse(settings.SettingsXml);
var metaDataField = ( from f in doc.Descendants("MetadataField") let fieldId = f.Attribute("FieldID") where fieldId != null && fieldId.Value == field.Id.ToString() select f ).SingleOrDefault();
if (metaDataField != null) { var viewSettings = ( from v in metaDataField.Elements("ViewSettings") let uniqueNodeId = v.Attribute("UniqueNodeId") where uniqueNodeId != null && uniqueNodeId.Value == term.Id.ToString() select v ).SingleOrDefault(); if (viewSettings == null) { metaDataField.Add( new XElement("ViewSettings", new XAttribute("UniqueNodeId", term.Id.ToString()), new XElement("View", new XAttribute("ViewId", view.ID.ToString()), new XAttribute("CachedName", view.Title), new XAttribute("Index", "0"), new XAttribute("CachedUrl", view.Url) ) ) ); } }
settings = new MetadataNavigationSettings(doc.ToString()); MetadataNavigationSettings.SetMetadataNavigationSettings(list, settings);
If you have a field called “Folder” it will not be available in the returned ListItem object
e.g. listItem["Folder"].ToString()
The inner workings of the ListItem object uses an ExpandoObject to store the properties. It seems it mixes this up in the FieldValues Collection with all your custom fields. The Folder property then takes the value from the FieldValues collection to make it available to the Folder property. Thus making your own Folder field “disappear”
Here is how you can replicate it.
Create a list based on the Custom List template
Add a column called “Folder” and make it a text field
Add a column called “DisplayName” and make it a text field
Add a column called “MyField” and make it a text field
Add a couple of dummy rows of data
Create a console application in VS that references Microsoft.SharePoint.Client and Microsoft.SharePoint.Client.Runtime
Add the following code to the Main method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
using (var context = new ClientContext("http://siteurl")) { var query = CamlQuery.CreateAllItemsQuery(); var listItems = context.Web.Lists.GetByTitle("Testing").GetItems(query);
Here is the code from .Net Reflector that shows the ListItem object populating the properties. It’s also worth noting that the other properties detailed in this method will have the same problem, but it’s unlikely that you’ll call a field FileSystemObject!
RunAs("http://asharepointsite", "THEDOMAIN\THEUSER", c => { // The code to execute. e.g. get a the UserProfileManager as the passed in user var upm = new UserProfileManager(c, true);
// Do some stuff to the UPM as the passed in user });
if (SPContext.Current != null) { if (SPContext.Current.Web != null) { currentUser = SPContext.Current.Web.CurrentUser; } }
SPSecurity.RunWithElevatedPrivileges(delegate { using (var site = new SPSite(siteUrl)) { using (var web = site.OpenWeb()) { try { var user = web.EnsureUser(userName);
To match the ScopeId in the EventData property of the SPAuditEntry to a SPListItem you need to use the hidden column ScopeId and not the Id property of SPListItem.
Here is what I mean.
The following XML is returned in the EventData proprty for a SPAuditEventType of SecRoleBindUpdate. To match the Scope returned in the XML to SPSite, SPWeb and SPList object you would use the Id property of this object, but not for the SPListItem.