Skip to main content

Reusable Business rules

One of the best aspects of Sitecore is its rules engine. It is easy to use and very extensible. I have worked on large projects which run multiple websites one thing that comes up is how can rules, which authors create, be reused? It is great we can add a personalization rule to a rendering but what if we have the same rule we want to apply multiple places? Can we do this in a way we don't have to go change that rule in each place?

One approach to this is using the predefined rules that come with Sitecore. These are located at /sitecore/system/Marketing Control Panel/Personalization/Predefined Rules.


Once you have created a predefined rule you can use it via personalization by click on the "predefined rules" sections when creating a new rule.


Once you have done this you have a reusable rule you can edit in one place but use in lots of different personalization locations. This is great and can be very helpful. However, it only gives you access to the condition, not the actions. So you can reuse the condition (if something true or false) but you don't have access to the actions (what you are personalizing, so a rendering or data source, etc). What if you want a way to reuse the condition and the expected action to execute? 

Out of the box, there is not a way to do this as the only place you can set both are in the presentation details of an item. So you could find a way to do inheritance of presentation details. That is an option and details of presentation or layout inheritance I hope to cover in a different blog. Here are some blogs on that topic if you need that now. Override Sitecore default mechanism of getting presentation details or Inheritance of presentation details

What I am going to focus on here is how to use an item as a data source and have a pipeline execute that rule and inject the personalization results of the rule of that item into your output. First what you are going to do is create a new template that has a "Rule" field that is of type "Rule". 


Nothing fancy here. The "Rules" type is a Sitecore out of the box type that allows you to add a business rule field to an item. This allows you to create a new item that will hold the personalization rule you want to reuse. 


Great, now you have a place to hold the rule you want to reuse, how do you get Sitecore to process and use it? To do this you need a pipeline processor. The below code is how you can do this. Now keep in mind that I am injecting a logging repository in the code so I can log things I care about. So if you are using this you will need to remove that or replace it with your own. 

The logic for this really starts at line 35. Here you get the data source item and see if it is of the template type we care about. If it is we need to inject the rule into the rendering properties the pipeline is going to process. We need to do this in two places in the arguments. We need to update the personalization rules that need to be executed, then we need to update the rendering XML stored in the rendering arguments.   


Once you have your code just patch the processor into the pipeline. 


To help visualize what is happening here think of the presentation details of an item. When you view the raw value of this field for an item you can see it is just XML data about how it is configured. So with this code, we are just pushing the configuration of our reusable rule field into this configuration. 

Now with the below code, the rule you inject will be executed and the data source your rendering ends up showing will be changed based on your rule configuration (or whatever action your rule was configured to take). 


Comments

Popular posts from this blog

Uniting Testing Expression Predicate with Moq

I recently was setting up a repository in a project with an interface on all repositories that took a predicate. As part of this I needed to mock out this call so I could unit test my code. The vast majority of samples out there for mocking an expression predicate just is It.IsAny<> which is not very helpful as it does not test anything other then verify it got a predicate. What if you actually want to test that you got a certain predicate though? It is actually pretty easy to do but not very straight forward.Here is what you do for the It.IsAny<> approach in case someone is looking for that. this.bindingRepository.Setup(c => c.Get(It.IsAny<Expression<Func<UserBinding, bool>>>())) .Returns(new List<UserBinding>() { defaultBinding }.AsQueryable()); This example just says to always return a collection of UserBindings that contain “defaultBinding” (which is an object I setup previously). Here is what it looks like when you want to pass in an expressi…

Excel XIRR and C#

I have spend that last couple days trying to figure out how to run and Excel XIRR function in a C# application. This process has been more painful that I thought it would have been when started. To save others (or myself the pain in the future if I have to do it again) I thought I would right a post about this (as post about XIRR in C# have been hard to come by). Lets start with the easy part first. In order to make this call you need to use the Microsoft.Office.Interop.Excel dll. When you use this dll take note of what version of the dll you are using. If you are using a version less then 12 (at the time of this writing 12 was the highest version) you will not have an XIRR function call. This does not mean you cannot still do XIRR though. As of version 12 (a.k.a Office 2007) the XIRR function is a built in function to Excel. Prior version need an add-in to use this function. Even if you have version 12 of the interop though it does not mean you will be able to use the function. The a…

MVVM light and Model Validation

I have been using the MVVM light toolkit for a project recently. It is a great toolkit but is missing a couple things and Laurent Bugnion does a good job trying to cover those holes. One of the things the toolkit does not support is Validation. The good news is there is a great CodePlex project out there call Fluent Validation that makes this pretty easy to add and really powerful. My objective was to add validation to my model so I could call “IsValid” on the model itself (similar to the MVC attribute approach). Fluent Validation has you create a new class file that holds you validation rules for a given model. This is the approach I took to enable each model to have an “IsValid” property and a “Errors” property that returns the validation errors.First I setup my ValidationFactory:publicclass ValidatorFactory : FluentValidation.ValidatorFactoryBase{publicoverride FluentValidation.IValidator CreateInstance(Type validatorType) {return SimpleIoc.Default.GetInstance(validatorType) as …

WPF Localization - RESX Option

About a year ago I was building a WPF project in .Net 3.0 and Visual Studio 2005. I wanted to revisit this subject and see what has changed in .Net 3.5 and Visual Studio 2008. I will make a few of these posts to try and cover all the different options (RESX option, LocBaml option, Resource Dictionary Option). In this blog I will focus on using a resx file to localize an application. To show how the resx option is done I created a WPF form with three labels on it. The first label has is text set inline in XAML, the second has it text set via code behind from the resx file and the third has its text set via XAML accessing the resx file. The first thing that needs to happen to setup a project for localization is a small change to the project file. To make this change you will need to open the project file in notepad (or some other generic editor). In the first PropertyGroup section you need to add the follow XML node <UICulture>en-US</UICulture>. So the project file node woul…

Experience Profile Anonymous, Unknown and Known contacts

When you first get started with Sitecore's experience profile the reporting for contacts can cause a little confusion. There are 3 terms that are thrown around, 1) Anonymous 2) Unknown 3) Known. When you read the docs they can bleed into each other a little.

First, have a read through the Sitecore tracking documentation to get a feel for what Sitecore is trying to do.

There are a couple key things here to first understand:

Unless you call "IdentifyAs()" for request the contact is always anonymous. Tracking of anonymous contacts is off by default. Even if you call "IdentifyAs()" if you don't set facet values for the contact (like first name and email) the contact will still show up in your experience profile as "unknown" (because it has no facet data to display).  Enabled Anonymous contacts


Notice in the picture I have two contacts marked in a red box. Those are my "known" contacts that I called "IdentifyAs" on. I know they say &…