Archive

Archive for April, 2011

Decoupling through the Rules Engine

April 28, 2011 2 comments

Recently I was designing a feature on a site that required dynamic behaviours. This kind of thing is right up the Sitecore rules engine’s alley so I made use of it in the design. But the use of the rules engine had larger benefits than simply meeting the requirements. More on that in just a second.

Before getting too far into this blog post I feel I should make mention of Sitecore 6.5 which landed in CTP last week and is now available on SDN for download. Apart from the usual bug fixes and performance enhancements the biggest changes are in OMS. In fact, it looks like OMS is getting a name change to DMS (Dynamic Marketing System), though being this is a CTP everything may be subject to change before RTM.

I’ve already had people asking if they should upgrade their solutions to Sitecore 6.5. At this very minute I would say no as the release is CTP. As soon as it hits RTM, go for it. Even if you’re not using DMS/OMS it’s always a good idea to keep as up-to-date as possible unless the most recent version has known issues that your solution can’t work around. Making smaller updates more regularly is generally easier than larger updates less frequently.

OK, so onto the rules engine.

What is the rules engine? The rules engine in Sitecore allows us to dynamically change things based on stuff that’s happening. Yes that’s a little vague, but that’s because the rules engine is used in so many part of Sitecore. But what I’ll be looking at specifically in this post is conditional rendering rules which allows for dynamically changing the behaviour of presentation components. There is a wide variety of conditions out of the box with Sitecore for determining when the rules should be applied. And we can even create our own conditions to cover scenarios that aren’t covered out of the box.

As I mentioned above, using the rules engine had greater benefits than simply meeting the requirements in that it allows decoupling the business logic from the implementation. Without the rules engine, every presentation object involved in the behaviour would need to have it’s code updated to implement the behaviour. This could be a lot of work and requires going back to the code for every small update. It also makes your code more complex and more difficult to understand.

Rules which you create for the rules engine consist of conditions and actions. Conditions convey something about the current request such as country of origin of the request, profile key comparisons or the logged on user. Actions cause something to happen when the conditions are met such as hide rendering, set rendering data source or set a rendering parameter.

To properly illustrate the power of the rules engine, let’s create a scenario we can work through. Let’s start simple and ensure our scenario can utilise out of the box rules engine components. Sitecore contains a lot of rules engine components out of the box and you should familiarise yourself with them by having a peek in /sitecore/system/settings/rules/conditional renderings (and the Sitecore 6.5 CTP which came out last week contains even more!). So for this simple scenario we want to set the data source of a rendering to a different item to read it’s data from when the user has viewed 5 or more pages on the site. In the real world, you might use this kind of thing to alter promotions displayed on a sidebar to the user to try and offer more enticing promotions the longer they stay on the site.

To configure this kind of personalisation we need to log into the Sitecore desktop, then open the marketing center application and expand the personalization item then select the rules item. This is where we’ll create our personalisation rule. Create a new Conditional Rendering Rule and name it “Different data source for longer visits” or something else descriptive. Now select the newly created rule and click the Edit Rule menu option on the rule field.

In the resulting rule set editor dialog, select the condition “where the page index compares to number”. This will cause that condition to be added to the current rule and highlight the text of the rule which is settable. Click the compares to link and change it to is greater than then click number and change it to 5. This is our complete condition. Now select the action we want to apply when the condition is true which is the “set data source to Item” action. Click the Item link to set the specific item we want to use as the data source. That is our completed rule.

image

Note the above dialog is from the Sitecore 6.5 CTP. If you’re using an earlier version of Sitecore your dialog will look different. A quick note about one of the differences with the 6.5 CTP. Notice the Add a new rule link at the bottom? This indicates we’ll be able to add multiple rules to a conditional rendering rule in Sitecore 6.5 (although the CTP this didn’t appear to work). This will save a lot of time when you have multiple rules to apply at once to a control.

Now we’ve defined our conditional rendering rule we can apply it to a rendering. Open the presentation definition for an item by navigating to the standard values of it’s template (cause we never define presentation directly on items), selecting the presentation tab then click the details button in the layout section. Click the control you want to apply the rule to (or click edit, then select the controls tab, then select the control and click the edit button) and in the personalization section tick the rule you created previously to have it active for this control. Click OK until all the dialog are closed, publish and you’re ready to go! Now when you visit more than 5 pages in a session the data source of the control you applied the rule to above will get changed.

Quick note about Sitecore 6.5 CTP differences (again). By default the personalization section of the control properties dialog is not shown. To display that section click the Sitecore orb at the top of the content editor and select Application Options. On the view tab select the Show the Personalization section checkbox. Sitecore 6.5 CTP also adds a new button to the Device Editor dialog (the dialog that lists all the controls and allows you to edit them) titled personalize that allows you to define personalisation rules directly on the control itself without having to first create a separate conditional rendering rule in the marketing centre. This will be great for one offs and basic personalisation as it’s limited in comparison to a conditional rendering rule. For more complex rules or rules you want to apply more than once to different components, then you’ll still want to create a conditional rendering rule item.

Now stop for a minute and assess what we’ve done. Without the rules engine we would have had to update the code of each control to first evaluate the condition, then secondly to adjust the behaviour of the control. By using the rules engine we’ve decoupled the business logic from the implementation. Now if we need to apply the same rule to another control it’s as simple as a little bit of configuration as opposed to the alternative if we weren’t using the rules engine, which would mean updating the code of those controls. And what if someone wanted a similar but different rule? With the rules engine we don’t have to update each control involved, instead we can just create the rendering rule and apply it.

But this wouldn’t be Sitecore unless we could extend it! And the rules engine is no exception. So let’s have a look at creating our own conditions and action.

Firstly, a custom action. The action we used above lets us change the data source to a specific item in the content tree, but I’d like to be able to set the data source by using a Sitecore query. We’ll need to start by creating our custom action as a new class which inherits Sitecore.Rules.Actions.RuleAction<T>.

using Sitecore.Rules.Actions; 
using Sitecore.Rules.ConditionalRenderings;

namespace RulesEngineDemo 
{
  public class QueryDataSourceAction<T> : RuleAction<T> 
    where T : ConditionalRenderingsRuleContext 
  {
    public string Query 
    {
      get;
      set;
    }

    public override void Apply(T ruleContext)
    { 
      var item = ruleContext.Item.Axes.SelectSingleItem(Query);
      if (item != null)
      {
        ruleContext.Reference.Settings.DataSource = item.ID.ToString();
      }
    }
  }
}

The Query property above will be automatically populated by the rules engine based on the user defined parameters to the action text which we’ll fill in when we register this class. Note that we’ve defined a constraint on the generic type T to ensure it’s a ConditionalRenderingsRuleContext which is used in the conditional rendering rules. The rules engine goes beyond just conditional rendering rules.

Next we need to register this class and create the action definition item. This is done inside Sitecore under the /sitecore/system/settings/rules/conditional renderings/actions. Create a new item based on the system/rules/action data template. Fill in the fully qualified type name of the class we created above into the type field. Now we need to define the action text.

We mark up the action text to tell the rules editor and engine how to present the settable parameters to the user and what kind they are. For our case we only need a single parameter to fill in the Query property of our class. This will be text as we’ll be expecting a Sitecore query. Fill in the text field with the following:

set data source using [Query,Text,,a query]

See how we define the directives for the rules engine inside the square brackets. There are 4 elements in the square brackets, each separated by a comma. The first element is the property of the action class this parameter will be set into. The next element describes the UI the user should use to enter the parameter. Take a peek at /sitecore/system/settings/rules/common/macros for a list of different UI elements you can use. The third element are parameters for the UI component. We don’t need any for our example so we leave it empty. The last element is the text to display in the rules editor when the parameter has not been set.

If you’ve done everything right you should now be able to apply this action as part of a rule. For testing, create a new conditional rendering rule with the condition of where true which means the action will always run (very handy for testing your actions). Now select the new action we created and specify the query. Something simple like setting the data source to the parent (..). Now go and adjust the personalization rules applied to a control in the presentation definition of an item, publish, then navigate to that page. Your query should be been run and the data source of the control changed.

We can also create our own conditions for the rules engine. Custom condition classes must inherit from one of the condition base classes, Sitecore.Rules.Conditions.OperatorCondition, Sitecore.Rules.Conditions.WhenCondition, or Sitecore.Rules.Conditions.StringOperatorCondition. For this demo let’s create a condition to detect when a query string key contains a certain value. This will be a string comparison operation so the class we need to inherit from will be Sitecore.Rules.Conditions.StringOperatorCondition. I also want to be able to set the query string key and value, so I’ll need to expose these as properties of the class.

using System.Web; 
using Sitecore.Rules;
using Sitecore.Rules.Conditions;

namespace RulesEngineDemo
{
  public class QueryStringCondition<T> :
    StringOperatorCondition<T> where T : RuleContext
  {
    public string Key
    {
      get;
      set;
    }

    public string Value
    {
      get;
      set;
    }

    protected override bool Execute(T ruleContext)
    {
      var qsValue = HttpContext.Current.Request.QueryString[Key];
      return base.Compare(qsValue ?? string.Empty,
        Value ?? string.Empty);
    }
  }
}

Notice in the Execute method above we use the base classes Compare method? This is because we don’t actually know what kind of comparison the user wants to make. This is a StringOperatorCondition which can use the StringOperator macro to allow the user to select how the text is compared (is equal, is equal case-insensitive, contains, not equal, etc).

Now we need to register this condition and define the condition text. This is similar to what we did above for actions, but we’ll put the condition definition under the conditions folder rather than the actions folder. In your condition definition item, enter the fully qualified name of the condition type above then enter the following as the text.

where the query string [Key,Text,,key] [operatorid,StringOperator,,compares to]
  [Value,Text,,value]

Being this is a condition, Sitecore will automatically make the where in the text above a link to negate the condition. The Key and Value parameters above should be straight forward. The operatorid parameter is provided by the base class of our custom condition type.

Now we can create a new conditional rendering rule using this condition to detect query string values. Go ahead and give it a try.

I must say I’m quite excited about the rules engine as I’m now discovering how to apply it in real projects and not just those contrived marketing examples we’ve all seen where the data source of a control is changed. The rules engine has so much more power than that, and it allows for loosely coupled logic and behaviours (have I mentioned that point enough yet?).

For more information on the rules engine check out the The Rules Engine Cookbook on the SDN.

Categories: Rules Engine, Sitecore

Calling Control

April 12, 2011 1 comment

Several years ago I remember watching a dnrTV (dot net rocks TV) episode featuring Venkat Subramaniam discussing Ruby like features of .NET 2 and C# 2. You can catch the episode at http://www.dnrtv.com/default.aspx?showNum=41. One programming technique that stuck in my head from that episode was to do with passing control inside a method back to the calling code to allow it to fill in the specific detail.

When implementing a method of a class, if you find yourself repeating the same code in several methods that code should be extracted as a separate method and called from each of the other methods requiring it. This means less code and this common logic is in a single location making maintenance much easier. This is fine when the common code doesn’t change, but what if you have small changes in the middle of the common code? For example you might have a bunch of error checking and resource allocation going on before you get to the specifics of the method and the only thing changing between the methods are a few lines of code that might also be nested several curly braces deep.

In Ruby the yield keyword works very different to what we’re used to in C#. In C# yield is used as a convenient way of creating an IEnumerable.

C#

public IEnumerable<int> GetNums()
{
  for (var i = 0; i < 5; i++)
    yield return i;
}

Rather than creating an output array or list, adding my elements to it then returning in the appropriate format, I can make use of the yield return statement to output all the values I want from the method and I’ll get back an IEnumerable<int> that I can iterate over. It’s less code and cleaner.

In Ruby the yield keyword is used to pass control back to the calling code so it can provide specific detail or use the data passed through yield.

Ruby

def doSomething
  for num in 0..5
    yield num
  end
end

doSomething { | data |
  puts data
}

In the above example I’m calling the doSomething method which calls the code block in the calling code each time the yield statement is called inside the method.

This is quite a nice technique. I have at times come across occurrences where most of the method I was working on was the same as another, except for a few lines of code in the middle.

In the dnrTV episode Venkat produced the same result in C# using delegates. Delegates are basically method pointers which will invoke a different method and allow you to pass methods into other code, a little like a functional language. Let’s take a look at how we could do the same in C# using anonymous delegates. For the following example try and imagine we’re trying to get typed data from a data store. The GetString method will return the typed data. This method will use the DataFromStore method which will get the raw data and call back to the GetString method to provide the formatting of the data.

C#

class ControlWithDelegate
{
  public delegate string GetData(object data);

  public string GetString(string key)
  {
    // get data from data store
    return DataFromStore(key, delegate(object data)
    {
      return (string)data;
    });
  }

  public string DataFromStore(string key, GetData formatter)
  {
    // get data from data store
    object data = "data from store using key";
    return formatter(data);
  }
}

The reason this is an anonymous delegate is because it’s declared inline. We haven’t declared a delegate which is another named method to use.

The GetString method calls the DataFromStore method passing the 2nd parameters as an anonymous delegate. Inside the DataFromStore method we can use that parameter as a method. This causes the code inside the anonymous delegate to execute. The result is then returned from DataFromStore to GetString which then returns the data to it’s caller.

This is a very elegant way of using the same technique as we can see in the Ruby example above. It allows us to pass control back to the calling code momentarily.

But I would like to make it smaller. I don’t like that I need to define the delegate signature. Well with the introduction of the Func delegates in C# 3, we no longer have to. Let’s rewrite the above example using Func delegates instead of our own defined delegate.

C#

class ControlWithFunc
{
  public string GetString(string key)
  {
    // get data from data store
    return DataFromStore(key, delegate(object data)
    {
      return (string)data;
    });
  }

  public string DataFromStore(string key, Func<object, string> formatter)
  {
    // get data from data store
    object data = "data from store using key";
    return formatter(data);
  }
}

I know it’s not much, but I like not having to define a delegate type which might only be used by a handful of methods.

Lambda expressions are a compact way of declaring anonymous delegates. I can compact the code slightly further by using a lambda expression instead of declaring the anonymous delegate.

C#

public string GetString(string key)
{
  // get data from data store
  return DataFromStore(key, data =>
  {
    return (string)data;
  });
}

public string DataFromStore(string key, Func<object, string> formatter)
{
  // get data from data store
  object data = "data from store using key";
  return formatter(data);
}

Just as a point of reference, here’s the equivalent Ruby code for the above C# sample.

Ruby

class MyClass
  def getString(key)
    dataFromStore(key) { |data| return data }
  end

  def dataFromStore(key)
    data = yield "data from store using key"
    return data
  end
end

Now let me give you a more real world example. The specific scenario I was recently working on was to do with creating a class to deal with fetching documents over HTTP. I needed to be able to fetch both text and binary documents. When it came to implement my GetTextDocument and GetBinaryDocument methods I found most of the method would be the same between those two. In both cases I need to created an HttpWebRequest, get the stream and clean up when done. The piece that would differ would be how I read the data from the stream and the return type. This lead me to exploring using the above technique to allow me to write less code.

First I’ll start with the common functionality to be used by both methods.

C#

private T GetDocument<T>(string url, Func<Stream, long, T> impl)
{
  if (!string.IsNullOrEmpty(url))
  {
    var request = HttpWebRequest.Create(url);
    using (var response = request.GetResponse())
    {
      using (var stream = response.GetResponseStream())
      {
        T output = impl(stream, response.ContentLength);
        return output;
      }
    }
  }
  else
    return default(T);
}

Note how I’m using generics to allow the calling code to define the type of data that will be returned. Now I’ll implement the GetTextDocument method.

C#

public string GetTextDocument(string url)
{
  return GetDocument(url, (stream, length) =>
  {
    var streamReader = new StreamReader(stream);
    return streamReader.ReadToEnd();
  });
}

And then the GetBinaryDocument method.

C#

return GetDocument(url, (stream, length) =>
{
  var chunkSize = 1024f;
  if (chunkSize > length)
    chunkSize = length;

  var read = 0;
  var offset = 0;

  var output = new byte[length];

  while((read = stream.Read(output, offset, (int)chunkSize)) > 0)
  {
    offset += read;

    if((offset + chunkSize) > length)
      chunkSize = length - offset;
  }

  return output;
});

And there you have it. An easy way to allow passing control of a method back to it’s caller to allow the caller to fill in specifics of a generic implementation.

Categories: .net, C#

Revolver 1.2 Released

Yesterday I released Revolver 1.2 for Sitecore 6.4. Releases for other Sitecore versions should be available over the next few days.

Along with a few bug fixes and behind the scenes stuff the following list provides a brief overview of updates made to Revolver for the 1.2 release.

Maximum Query Results Warning

Sitecore query provides a nice way to query for Sitecore items using an XPath like syntax. A query which pulls back lots of items can affect performance. To mitigate this Sitecore contains a setting in web.config called Query.MaxItems which controls the maximum number of items to return for a SItecore query. By default this value is quite low, set to 100. The issue is you may have more than 100 items you need to return from the query. To make that work you need to adjust the value of the Query.MaxItems setting. Revolver will now warn you when using the query command if the number of results returned is the same number as that of the Query.MaxItems setting indicating you may not have all the results.

Sitecore DateUtils for Expression Engine

Expressions in Revolver provide a convenient way to specify matching criteria in the find command.

find -r -e (@title = myitem with ignorecase or @__created > 20110404 as date) (sf myfield updated)

The Revolver expression engine now uses the Sitecore DateUtil to parse the date you enter when using the as date modifier. This allows specifying friendly tokens for common date expressions such as “now”, “today”, “tomorrow” and “yesterday”

find -r -e (@__created > yesterday as date) pwd

Lazy CD

This is one of my favourite new features. The cd command has been updated to allow you to be lazy when only traversing down a single level and not type all the characters of the item you want to change to. Previously you always had to type the full name of the item.

So if I was on /sitecore/content/home and I had child items of item1, another item and summary item, I could change to the summary item child item by simply typing the following:

cd s

If a child item of the same name cannot be found Revolver will try and match the start of an item’s name with the name entered in the command. It will use as many characters as you’ve entered as well, so if you have myitem and myfav you can use myi to go to myitem. Keep in mind this only works for going down a single level. cd c/h will not work.

CD by index

The cd command now also supports selecting an item by (zero-based) index, So I can change to the 4th child item by using:

cd [3]

This also works for multiple items of the same name. So if I have multiple children called myitem I could select the second item of that name by using:

cd myitem[2]

Clone Support

Revolver 1.2 now adds support for Sitecore 6.4 cloned items. You can use the new clone command to clone and unclone items as well as accept and reject changes to the clone targets.

The Sitecore UI doesn’t currently have a facility to accept (or reject) all clone updates for the entire system or just a subtree of the content tree. Using the new clone command combined with the find command accepting all updates from the clone source item down a subtree is as simple as:

find -r (clone -a)

Script Execution Directives

You can now control how scripts are executed using the new script execution directives. Execution directives can be placed on any line in a script and always start with an @ symbol. The following is a list of directives and their affect:

@echooff: Do not display the output of the script on the UI

@echoon: Display the output of the script on the UI

@stoponerror: Stop executing the script if an error occurs

Script directive only affect the lines of the script that appear after the directive. Consider the following script example:

@echooff
@stoponerror
set previtem < (ga -a id)
cd < (ga -a templateid)
cd < (find -ns -r -a name ($1$) (ga -a id))
@echoon
echo id: < (ga -a id)
echo name: < (ga -a name)
echo type: < (gf -f type)
echo source: < (gf -f source)
@echooff
cd $previtem$
set previtem

Note how the @echooff and @echoon directives have been used to hide portions of the output but allow it in other portions.

Path on PWD

You can now specify a path parameter for the print working directory (pwd) command. This may seem a bit useless at first, but remember you can specify an ID as a path, so this makes finding the path of an item ID very easy.

Copy and IDs

The copy command (cp) was updated to keep the same ID for an item when copying to a different database but change it when copying within the same database.

Copy Media

The copy command was updated further to also copy the media blob of a media library item when copying to a different DB. You’ll appreciate this if you’ve ever tried to copy (or transfer) a media asset from one database to another. The item itself will copy, but the blob isn’t included. Revolver will automatically detect media assets being copied and include the blob without any alteration to the parameters.

Copy Single Field to Language

The Copy Language command (cpl) has been updated to allow specifying a single field to copy from the current language to another language rather than just taking all fields across in one hit. Keep in mind you’ll still need to use the overwrite parameter (-o) if the target field is populated.

cpl –f title –o da

The above command copies the title field from the current item in the current language to the current item in the Danish language, overwriting any existing value in the Danish title field.

Links by Field

The links command has been updated to allow specifying a source field the link must originate from. This allows you to zero in on specific kinds of links. For example, to view all clone items that use the current item as a source, execute the following:

links –f __source

Note I no longer have to specify the incoming (-i), outgoing (-o) and bad (-b) link parameters to include those kinds of links in the output. When none of those parameters are specified then all links are retrieved. You can still specify the kinds of links to display as well:

links -i -o

Field Information Script

That script example above used in the execution directives? That was actually taken from the field info (fi) script which now ships with Revolver. This script displays information about a field of the current item. To use it, just specify the name of the field to show information on:

fi text

Conclusion

So that’s it for the updates in the 1.2 release. I already have a large list of improvements and additions to make for the next minor and major version of the module as well. If you’ve got any feedback or would like to see some additional features in the module, drop me a line at alistair.deneys@codeflood.net.

Categories: Revolver, Sitecore
Follow

Get every new post delivered to your Inbox.