March 26, 2013

Use and evaluate the Rule field type

In sitecore one of the field you can use is the "Rule" field. This field is very powerfull and you can easilly implmeent your own rules. Here is a very small tutorial on it.

First of all, on your template you should select the field of thype "Rule":

Now on your item you have an editor like this one:




And the following function return is a rule field is true:
public bool EvaluateRule(string fieldName, Item item) 
{
 var ruleContext = new RuleContext();
 foreach (Rule<RuleContext> rule in RuleFactory.GetRules<RuleContext>(new[] { item }, fieldName).Rules)
 {
     if (rule.Condition != null)
     {
  var stack = new RuleStack();
  rule.Condition.Evaluate(ruleContext, stack);

  if (ruleContext.IsAborted)
  {
      continue;
  }
  if ((stack.Count != 0) && ((bool)stack.Pop()))
  {
      return true;
  }
     }
 }
 
 return false;
}

Ajax lazy loading with Sitecore

For one of our project we need to call some sublayout in ajax. This allow you to do some pagination or lazy loading and let sitecore resolve the context.

To do that, we will create our own LayoutResolver to respond to our query with only the corresponding rendering.

Our call ajax wll look like:
var url = "http://myurl/myItem?UseAjax=true&amp;PresentationId=BACBFEE1-C0BB-4D8E-BA1A-D9F50CCA5B7F";

$.ajax({
 type: 'GET',
 url: url
}).done(function (data) {
 //Your code
});

We will also need a layout for the ajax queries (in the following code the MY_AJAX_LAYOUT_ID is the id of this layout) and this layout will only contain one placeholder (MY_AJAX_PLACEHOLDER in the code)

Now here is the custom layout resolver (look at the comments into the code):
using System;
using System.Linq;
using System.Web;
using Sitecore.Data.Items;
using Sitecore.Pipelines.HttpRequest;

namespace MyNamespace
{
    public class AjaxLayoutResolver : LayoutResolver
    {
        public override void Process(HttpRequestArgs args)
        {
            bool useAjax;
     //First of all let's check if we are in ajax mode or not if not don't continue
            var result = bool.TryParse(HttpContext.Current.Request.Params["UseAjax], out useAjax);
            if (!result || !useAjax)
            {
                return;
            }

     //The second parameter we need to pass is the PresentationId if not present the query if not valid -> don't continue
            var presentationId = HttpContext.Current.Request.Params["PresentationId"];
            if (string.IsNullOrEmpty(presentationId))
            {
                return;
            }

     //If the current item is null return
            if (Sitecore.Context.Item == null)
            {
                return;
            }

     //Let's resolve the sublayout
            try
            {
  //Get the list of rendering for the current item
                var renderings = Sitecore.Context.Item.Visualization.GetRenderings(Sitecore.Context.Device, false);
  //If found
                if (renderings != null && renderings.Any())
                {
      //Get the first rendering corresponding to the requested one
                    var rendering = renderings.First(sublayout => sublayout.RenderingID.ToString().Equals(presentationId));
                    if (rendering != null)
                    {             
                        //Put this rendering into ajax layout
                        rendering.Placeholder = MY_AJAX_PLACEHOLDER;
                        var layoutItem = Sitecore.Context.Database.GetItem(MY_AJAX_LAYOUT_ID);
                        if (layoutItem != null)
                        {
                            var layout = new LayoutItem(layoutItem);
                            Sitecore.Context.Page.FilePath = layout.FilePath;
                            Sitecore.Context.Page.ClearRenderings();
                            Sitecore.Context.Page.AddRendering(rendering);
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                Log.Warn("Cannot render this!", this, exception);
            }
        }
    }
}
And of could you need to include this resolver after the existing one by adding this into a .config file in \App_Config\Include\
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <httpRequestBegin>          
          <processor patch:after="*[@type='Sitecore.Pipelines.HttpRequest.LayoutResolver, Sitecore.Kernel']" type="MyNamespace.AjaxLayoutResolver, MyNamespace"/>          
      </httpRequestBegin>
    </pipelines>
  </sitecore>
</configuration>