LibrarySites.Banner

Roles and Rules, Part 1

Consider the following use case: a content author wants to display a content block that offers a special deal to customers who are subscribed to the company's monthly newsletter.  Naturally, the newsletter is managed using Sitecore's Email Campaign Manager, which means that the mailing list is managed using a role.  Information about this special deal should only be visible to customers who receive the newsletter.  This is an example of the kind of personalization that a website might use.

On a technical level, the content block is implemented as a control that the content author is able to position on the web page using a control. There are several ways to satisfy this requirement, but the approach I am going to use takes advantage of Sitecore's conditional rendering capabilities. This will allow me to create a rule that determines if a visitor is a member of a specific group. Once I have this rule defined, I can reuse that rule throughout the site whenever I need to determine if the visitor is subscribed to the mailing list.

Background Information

If you haven't done so already, you should read the Rules Engine Cookbook available on SDN. In addition, I also recommend reading An OMS Rules Engine Example, a blog post written last year by Mike Casey.

Step 1: Create the condition class

Sitecore already has the ability to determine if a user is a member of a role. What I need to create is a class that the rules engine can invoke in order to use this functionality. Create a .NET class using the following code:

using System;
using Sitecore.Rules;
using Sitecore.Rules.Conditions;
namespace Sitecore.ProductMarketing.Rules
{
    public class WhenRole<T> : WhenCondition<T> where T: RuleContext
    {
        public string Role { get; set; }
        protected override bool Execute(T ruleContext)
        {
            if (! string.IsNullOrEmpty(this.Role))
            {
                return Sitecore.Context.User.IsInRole(this.Role); 
            }
            return false;
        }
    }
}

There isn't much code to write here. The Role property is used to store the name of the role that a Sitecore user will provide when he configures a rule that uses this condition. The Execute method contains the logic to check if the current user is a member of the specified role.

Step 2: Create the condition item

The Condition item serves a couple of purposes. It tells the rules engine to use the .NET class created in the previous step. It also provides details to the rules engine for how the condition should be displayed in the rule editor interface.

Create the following item:

* parent item: /sitecore/system/Settings/Rules/Common/Conditions
* template: /sitecore/templates/System/Rules/Condition
* item name: When Role

Set the following field value. The rules engine uses this field to determine how to display the rule in the rule editor. This describes the fields in the .NET class, along with instructions that the rule editor uses to create a user interface that allows a Sitecore user to set values for the variables:

* section: Data
* field name: Text
* value: where the user is a member of [role,,,specific role]

Set the following field value. This field tells the rules engine which .NET class contains the logic for determining if the user is a member of a specific role:

* section: Script
* field name: Type
* value: Sitecore.ProductMarketing.Rules.WhenRole, Sitecore.ProductMarketing.Rules

Step 3: Create a rule using the condition

I need a rule that can be used to show a control to visitors who are members of a certain role. Conditional rendering is the term Sitecore uses to describe a requirement like this. And in Sitecore, conditional rendering is a matter of hiding - not showing - a control under certain conditions. That isn't a problem, it just means I need to change the words I use. What I really want to do is hide the control for all users except those users assigned to a certain role. Same result, different words.

While the condition I created is generic, the rule that uses the condition is pretty specific. It's controlling conditional rendering, so I need to create the rule in the proper location in the content tree in order for Sitecore to find it when Sitecore displays a list of available conditional rendering rules to the content author.

  1. Create the following item:
    * parent item: /sitecore/system/Marketing Center/Personalization/Rules
    * template: /sitecore/templates/System/Rules/Conditional Rendering Rule
    * item name: Visitor Is Subscribed To Newsletter
  2. Set the following field value:
    * section: Data
    * field name: Text
    * value: Visitor Is Subscribed To Newsletter
  3. Click the Edit Rule button.
      
  4. The Rule Set Editor dialog appears. In the conditions box, click the link "where the user is a member of specific role".
    select condition 
  5. In the Actions box, select the "hide rendering" action by checking the checkbox.
    action added 
  6. In the Rule description box, click the link "where". This changes "where" to "except where". Remember, the rule results in a control being hidden from all visitors except those who are a member of a specific role.
    click where
  7. In the Rule description box, click the link "specific role".
    click specific role
  8. A popup dialog box appears. This value must match the name of the role that the newsletter subscribers are members of. In my case, the name of the role is "Emailcampaign\Newsletter Subscribers Member". Click the OK button to save the role name.
    prompt for role
  9. The Rule Set Editor dialog appears. Click the OK button to save the rule.
    role changed 
  10. Back in the Content Editor I see the finished rule.  Save the item.
    finished rule

Next Steps

Now the rule can be applied to any control that is assigned in an item's presentation details. One limitation of this approach is that the person configuring the rule must know the name of the role, and must manually enter the name. With a couple of small changes, I can make this solution much more usable by displaying a list of available roles. I will cover that in my next post.