Problems hiding or setting the audience on a link within the quick launch
-
29-09-2020 - |
Question
Good Morning All, I'm running into an issue where I would like to hide and show links on the quick launch based on a specific SharePoint group. I know how you can do it through the browser, but I'm to do it through code, either through a feature or master page. I do have publishing enabled which allows me to configure both the global and quick launch navigation. My first attempt was to set the "Audience" on link based on a specific SharePoint group (See code below)
SPNavigation spSiteNav = spWeb.Navigation;
SPNavigationNodeCollection spSiteQuickLaunch = spSiteNav.QuickLaunch;
SPNavigationNode spBaseHeading = spWeb.Navigation.QuickLaunch.Cast<SPNavigationNode>().Where(a => a.Title == "I need to").FirstOrDefault();
if (spBaseHeading != null){
string webAppRelativePath = spWeb.ServerRelativeUrl;
if (!webAppRelativePath.EndsWith("/")){ webAppRelativePath += "/";}
string MemPageUrl = string.Format("{0}{1}", webAppRelativePath, "SitePages/CreateNewMemo.aspx");
SPNavigationNode MemoPageLink = spBaseHeading.Children.Cast<SPNavigationNode>().Where(a => a.Url == MemPageUrl).FirstOrDefault();
MemoPageLink.Properties["Audience"] = string.Format(";;;;{0}", "Authors");
MemoPageLink.Update();
}
No luck, the code sets the audience on the link, but non "Authors" members can still see the link on the quick launch.
Then I tried setting the IsVisible property (See code below):
SPNavigation spSiteNav = spWeb.Navigation;
SPNavigationNodeCollection spSiteQuickLaunch = spSiteNav.QuickLaunch;
SPNavigationNode spBaseHeading = spWeb.Navigation.QuickLaunch.Cast<SPNavigationNode>().Where(a => a.Title == "I need to").FirstOrDefault();
if (spBaseHeading != null){
string webAppRelativePath = spWeb.ServerRelativeUrl;
if (!webAppRelativePath.EndsWith("/")){webAppRelativePath += "/";}
string MemPageUrl = string.Format("{0}{1}", webAppRelativePath, "SitePages/CreateNewMemo.aspx");
SPNavigationNode MemoPageLink = spBaseHeading.Children.Cast<SPNavigationNode>().Where(a => a.Url == MemPageUrl).FirstOrDefault();
MemoPageLink.IsVisible = false;
MemoPageLink.Update();
}
No luck again. The property is set, but the link is still visible to non "Authors" members.
I'm lost, any help would be greatly appreciate.
Thank you in advance....
Solution
How to manage audience targeting for Navigation using SSOM
UpdateNavigationNodeAudience
method allows to set audience targeting for Navigation node:
public static void UpdateNavigationNodeAudience(SPWeb web, SPNavigationNode node, Guid[] spAudienceIDs, string[] spGroupNames, string[] adGroupNames)
{
var audienceProps = new Dictionary<string, string>();
audienceProps["SharepointAudienceID"] = spAudienceIDs == null ? string.Empty : string.Join(",", spAudienceIDs.Select(a => a.ToString()).ToArray());
audienceProps["SharepointGroup"] = spGroupNames == null ? string.Empty : string.Join(",", spGroupNames);
audienceProps["ActiveDirectoryGroupObjectLDAPPath"] = adGroupNames == null ? string.Empty : string.Join("\n", adGroupNames);
var audienceValue = string.Format("{0};;{1};;{2}", audienceProps["SharepointAudienceID"], audienceProps["ActiveDirectoryGroupObjectLDAPPath"], audienceProps["SharepointGroup"]);
node.Properties["Audience"] = audienceValue;
node.Update();
}
Note: It has been tested in SharePoint 2010
Example
The below example demonstrates how to target Quick Launch menu nodes to SharePoint Group named Authors
:
using (var site = new SPSite(siteUrl))
{
using (var web = site.OpenWeb())
{
var quickLaunch = web.Navigation.QuickLaunch;
foreach (SPNavigationNode node in quickLaunch)
{
var spGroupNames = new[] {"Authors"};
UpdateNavigationNodeAudience(web, node, null, spGroupNames, null);
}
}
}
About Audience value format in navigation
The value has the following format:
{SharepointAudienceID};;{ActiveDirectoryGroupObjectLDAPPath};;{SharepointGroup}
where
{SharepointAudienceID}
- SharePoint Audience ID. The delimiter,
is used to specify multiple values{ActiveDirectoryGroupObjectLDAPPath}
- AD Group Name. The delimiter\n
is used to specify multiple values{SharepointGroup}
- SP Group Name. The delimiter,
is used to specify multiple values
How to hide Pages/Webs from Navigation
Use the following properties to control page/web visibility:
- PublishingWeb.IncludeInCurrentNavigation - controls whether this Web site is included by PortalSiteMapProvider objects that have NavigationType set to Current
- PublishingPage.IncludeInCurrentNavigation - Gets or sets a value that indicates whether the PublishingPage object is included by PortalSitemapProviders that have NavigationType set to "Current"
The HidePageFromCurrentNavigation
method hides page from current navigation:
public static void HidePageFromCurrentNavigation(SPWeb web,string pageUrl)
{
var publishingWeb = PublishingWeb.GetPublishingWeb(web);
var query = new SPQuery
{
Query = string.Format(@"<Where><Eq><FieldRef Name='FileRef'></FieldRef><Value Type='Text'>{0}</Value></Eq></Where>",pageUrl)
};
var pages = publishingWeb.GetPublishingPages(query);
if (pages.Count == 1)
{
pages[0].IncludeInCurrentNavigation = false;
}
}
The HideWebFromCurrentNavigation
method hides web from current navigation:
public static void HideWebFromCurrentNavigation(SPWeb parentWeb, string webUrl)
{
var web = parentWeb.Webs.FirstOrDefault(w => w.ServerRelativeUrl == webUrl);
if (web != null)
{
var publishingWeb = PublishingWeb.GetPublishingWeb(web);
publishingWeb.IncludeInCurrentNavigation = false;
}
}
Example
The example demonstrates how to hide all pages and webs from current navigation:
using (var site = new SPSite(siteUrl))
{
using (var web = site.OpenWeb())
{
var quickLaunch = web.Navigation.QuickLaunch;
foreach (SPNavigationNode node in quickLaunch)
{
var nodeType = (string)node.Properties["NodeType"];
if (nodeType == "Page") //Page node?
{
HidePageFromCurrentNavigation(web, node.Url);
}
else if (nodeType == "Area") //Web node?
{
HideWebFromCurrentNavigation(web, node.Url);
}
}
}
}
OTHER TIPS
For SharePoint 2013 you need to enable the Site Collection Feature "SharePoint Server Publishing Infrastructure" for audience target to work.