Q:

Problems hiding or setting the audience on a link within the quick launch

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....

A:

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);    
            }
       }
    }
 }

