Saturday, 29 March 2014

Cookie Based Sitecore Rule Conditions

I recently encountered a situation where I felt it would be beneficial to use cookie values to influence conditional rendering in Sitecore. I assumed there must already be some code for this on the web. But after a Googling a few different keyword combinations I couldn't find anything, and by my reckoning that absence makes it suitable blog material.


I've written 3 rule conditions that can be used to evaluate cookies included in a request. If you're not familiar with process of creating custom conditions, then Brian Pedersen's article on the subject is a good place to start.

I must admit this is a bit of an academic exercise really. I haven't given the practical applications a great deal of thought, but please leave a comment if you can think of any interesting uses or adaptations.




1. Cookie Exists Condition

The first condition simply checks whether the incoming request includes a specific cookie. The user only needs to supply the name of the cookie.

Text field: where the [CookieName,,,specific] cookie exists
public class CookieExists : WhenCondition where T : RuleContext
{
    public string CookieName { get; set; }

    protected override bool Execute(T ruleContext)
    {
        if (String.IsNullOrEmpty(CookieName))
            return false;

        if (HttpContext.Current.Request.Cookies[CookieName] == null)
            return false;

        return true;
    }
}


2. String Cookie Value Condition

This time we're comparing the value of a request's cookie with one specified in the condition using Sitecore's standard string comparison operators. The user needs to supply the cookie name, the comparison value, and the operator.

Text field:
where the [CookieName,,,specific] cookie string value [operatorid,StringOperator,,compares to] [CookieValue,,,specific value]
public class TextCookieValue : StringOperatorCondition where T : RuleContext
{
    public string CookieName { get; set; }
    public string CookieValue { get; set; }

    protected override bool Execute(T ruleContext)
    {
        if (String.IsNullOrEmpty(CookieName))
            return false;

        if (String.IsNullOrEmpty(CookieValue))
            return false;

        if (HttpContext.Current.Request.Cookies[CookieName] == null)
            return false;

        var actualVal = HttpContext.Current.Request.Cookies[CookieName].Value;

        if (String.IsNullOrEmpty(actualVal))
            return false;

        return Compare(CookieValue, actualVal);
    }
}


3. Numeric Cookie Value Condition

The final condition assumes that the request contains a cookie with number value and Sitecore's standard numeric operators are used for the comparison. The user needs to supply the cookie name, the comparison value, and the operator.

Text field:
where the [CookieName,,,specific] cookie numeric value [operatorid,Operator,,compares to] [CookieValue,PositiveInteger,defaultValue=&validation=%5E%5C-%7B0%2C1%7D%5Cd%2B(.%5Cd%2B)%7B0%2C1%7D%24&validationText=Please enter a valid number.,specific value]
public class NumericCookieValue : OperatorCondition where T : RuleContext
{
    public string CookieName { get; set; }
    public string CookieValue { get; set; }

    protected override bool Execute(T ruleContext)
    {
        if (String.IsNullOrEmpty(CookieName))
            return false;

        if (String.IsNullOrEmpty(CookieValue))
            return false;

        if (HttpContext.Current.Request.Cookies[CookieName] == null)
            return false;

        double parsedTestVal;
        if (!double.TryParse(CookieValue, out parsedTestVal))
            return false;

        String actualVal = HttpContext.Current.Request.Cookies[CookieName].Value;

        if (String.IsNullOrEmpty(actualVal))
            return false;

        double parsedCookieVal;
        if (!double.TryParse(actualVal, out parsedCookieVal))
            return false;

        ConditionOperator op = GetOperator();
        return ValuesCompare(parsedTestVal, parsedCookieVal, op);
    }

    private bool ValuesCompare(double val1, double val2, ConditionOperator op)
    {
        switch (op)
        {
            case ConditionOperator.Equal:
                return val1 == val2;
            case ConditionOperator.GreaterThanOrEqual:
                return val1 >= val2;
            case ConditionOperator.GreaterThan:
                return val1 > val2;
            case ConditionOperator.LessThanOrEqual:
                return val1 <= val2;
            case ConditionOperator.LessThan:
                return val1 < val2;
            case ConditionOperator.NotEqual:
                return val1 != val2;
            default:
                return false;
        }
    }
}
I realise that the kind of people who create conditional rendering rules are not typically the same people who concern themselves with the contents of cookies, but I've been proven wrong on that front more than once recently. So maybe someone might take these ideas and put them to good use.

EDIT: I now also have a post illustrating a rule action for setting cookies.