Anders Hattestad
Jun 30, 2011
  7639
(3 votes)

How to make Property LinkCollection use Visitor Groups

I have started to look some more into how the visitor groups are handled in EPiServer. It’s a function that allows parts of a text inside the editor to only be displayed for some user groups.

This function can be used other places also. For instance I wanted to make a LinkCollection where I could set for each link a visitor group.

I found one blog post by Paul Smith that show how we check if a user is in a visitor group.

But first I had to extend the normal PropertyLinkCollection with an extra column for visitor groups.

To archive this I had to copy the user control that is used by the Link Collection property.

image

And I had to reverse engineer the popup function from the editor so I could set and retrieve the selected visitor groups. basicly its only to open a dialog like this

Code Snippet
  1. EPi.CreateDialog(personalizedEditorUrl+"?groups="+groups+"&contentGroup="+contentGroup, onDialogComplete, onCompleteArguments , dialogArguments, {width: 460, height: 450, scrollbars:"no"});

where the url is

UriSupport.ResolveUrlFromUIBySettings("Editor/Dialogs/PersonalizedContent.aspx")

 

image

Then I needed to add these new attributes to the links. I just added them to the LinkItem as an attribute, so the new attributes will be added to the links link this:

image

In edit mode I then created a method that took an LinkItem as an argument and found out all the visitor groups it contains

Code Snippet
  1. {
  2.     string result = "";
  3.     string result2 = "";
  4.     var groups = GetAttribute(item, "data-groups");
  5.     if (!string.IsNullOrEmpty(groups))
  6.     {
  7.         var store = new VisitorGroupStore();
  8.         foreach (var id in groups.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
  9.             result += "<div class='epi_vg'>" +  store.Load(new Guid(id)).Name + "</div>";
  10.         if (result != "")
  11.             result = "<div class='epi_pc_l'>" + result + "</div>";
  12.     }
  13.     var contentgroup = GetAttribute(item, "data-contentgroups");
  14.     if (!string.IsNullOrEmpty(contentgroup))
  15.     {
  16.         foreach (var id in contentgroup.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
  17.             result2 += "<div class='epi_lg'><span>" + id + "</span></div>";
  18.         if (result2 != "")
  19.             result2 = "<div class='epi_pc_t'>" + result2 + "</div>";
  20.     }
  21.     return result + result2;
  22. }
Then I needed to filter the normal view of this Property, so I hide those links I’m not allowed to see. as far as I can understand this concept the check could be done like this. But if anyone have any pointers to if this is wrong, or should be done in another way please let me know.

Code Snippet
  1. public override void CreateDefaultControls()
  2. {
  3.     this.CopyWebAttributes(this);
  4.     HtmlGenericControl htmlGenericControl = new HtmlGenericControl("ul");
  5.     if (!string.IsNullOrEmpty(this.CssClass))
  6.         htmlGenericControl.Attributes.Add("class", this.CssClass);
  7.     this.Controls.Add(htmlGenericControl);
  8.     var helper = new VisitorGroupHelper();
  9.     var store = new VisitorGroupStore();
  10.     foreach (LinkItem current in this.PropertyLinkCollection)
  11.     {
  12.         var groups = GetAttribute(current, "data-groups");
  13.         var show = true;
  14.         if (!string.IsNullOrEmpty(groups))
  15.         {
  16.             show = false;
  17.             foreach (string id in groups.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
  18.             {
  19.                 var group = store.Load(new Guid(id));
  20.                 if (helper.IsPrincipalInGroup(EPiServer.Security.PrincipalInfo.CurrentPrincipal, group.Name))
  21.                     show = true;
  22.             }
  23.         }
  24.         try
  25.         {
  26.             var url = new UrlBuilder(current.Href);
  27.             bool isEPiServerPage = PermanentLinkMapStore.ToMapped(url);
  28.             if (isEPiServerPage)
  29.             {
  30.                 var page = DataFactory.Instance.GetPage(PermanentLinkUtility.GetPageReference(url));
  31.  
  32.                 if (page != null)
  33.                 {
  34.                     if (!page.ACL.QueryDistinctAccess(AccessLevel.Read))
  35.                         show = false;
  36.                 }
  37.             }
  38.         }
  39.         catch { }
  40.         if (show)
  41.         {
  42.             HtmlGenericControl htmlGenericControl2 = new HtmlGenericControl("li");
  43.             Literal literal = new Literal();
  44.             literal.Text = current.ToMappedLink();
  45.             htmlGenericControl2.Controls.Add(literal);
  46.             htmlGenericControl.Controls.Add(htmlGenericControl2);
  47.         }
  48.     }
  49. }

I also added a check if the link points to a episerver page that only displays links that the user have read access to.

Then

image

will return

image

and the link vg is removed

The only think I than lack is the ability to change the visitor groups in view mode. like this

image

I need to make my property implements the IPersonalizedRoles

Code Snippet
  1. [PageDefinitionTypePlugIn]
  2. [Serializable]
  3. public class PropertyLinkCollectionWithContentGroups : PropertyLinkCollection, IPersonalizedRoles
  4. {
  5.     public PropertyLinkCollectionWithContentGroups():base()
  6.     {
  7.     }
  8.     public override IPropertyControl CreatePropertyControl()
  9.     {
  10.         return new PropertyLinkCollectionWithContentGroupsControl();
  11.     }
  12.     protected string GetAttribute(LinkItem linkItem, string key)
  13.     {
  14.         if (linkItem.Attributes.ContainsKey(key))
  15.             return linkItem.Attributes[key];
  16.         return "";
  17.     }
  18.     public override IEnumerable<string> GetRoles()
  19.     {
  20.         List<string> list = new List<string>();
  21.         foreach (var link in Links)
  22.         {
  23.             var groups = GetAttribute(link, "data-groups");
  24.             if (!string.IsNullOrEmpty(groups))
  25.             {
  26.                 foreach (string id in groups.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
  27.                 {
  28.                     if (!list.Contains(id))
  29.                         list.Add(id);
  30.                 }
  31.             }
  32.         }
  33.         return list;
  34.     }
  35. }

and only return the id’s in a list of strings. then the visitor group filer will so these groups

image

The code is on property file, and one user control. If you copy those down and place them in a folder named Itera and add EPiServer.ApplicationModules and EPiServer.UI to your reference and compile then you are good to go.

Code is available here

Jun 30, 2011

Comments

Anders Hattestad
Anders Hattestad Jun 30, 2011 02:36 PM

Added some code in the CreateDefaultControls() that checks if the link points to a episerver page, and then checks access rights

Jun 30, 2011 02:50 PM

Very nice, was thinking about this myself so you beat me to it!

Anders Hattestad
Anders Hattestad Jun 30, 2011 03:02 PM

Thanks David, and sorry I beat you to it :)

Jul 4, 2011 08:39 AM

Looks sweet!

Please login to comment.
Latest blogs
Opti ID overview

Opti ID allows you to log in once and switch between Optimizely products using Okta, Entra ID, or a local account. You can also manage all your use...

K Khan | Jul 26, 2024

Getting Started with Optimizely SaaS using Next.js Starter App - Extend a component - Part 3

This is the final part of our Optimizely SaaS CMS proof-of-concept (POC) blog series. In this post, we'll dive into extending a component within th...

Raghavendra Murthy | Jul 23, 2024 | Syndicated blog

Optimizely Graph – Faceting with Geta Categories

Overview As Optimizely Graph (and Content Cloud SaaS) makes its global debut, it is known that there are going to be some bugs and quirks. One of t...

Eric Markson | Jul 22, 2024 | Syndicated blog

Integration Bynder (DAM) with Optimizely

Bynder is a comprehensive digital asset management (DAM) platform that enables businesses to efficiently manage, store, organize, and share their...

Sanjay Kumar | Jul 22, 2024

Frontend Hosting for SaaS CMS Solutions

Introduction Now that CMS SaaS Core has gone into general availability, it is a good time to start discussing where to host the head. SaaS Core is...

Minesh Shah (Netcel) | Jul 20, 2024

Optimizely London Dev Meetup 11th July 2024

On 11th July 2024 in London Niteco and Netcel along with Optimizely ran the London Developer meetup. There was an great agenda of talks that we put...

Scott Reed | Jul 19, 2024