Creating fallback values using the RenderField pipeline

I have previously shown my support for pipelines in Sitecore and I have used pipelines to modify the request header, to create contenteditor warnings, and I have shown how to add parameters to pipelines.

Here is another pipeline trick: Using the RenderField pipeline to create fallback values. The RenderField pipeline is the pipeline that Sitecore uses when rendering the value from the Sitecore database to the frontend. The pipeline ensures that fields can be used using Web Editing.

The pipeline is used by the sc:FieldRenderer web control when you render fields from web pages and user controls (.aspx and .ascx files). If you are an XSLT fan, you already know the sc:text, sc:html and sc:field XSLT extensions, that you use to render contents. And you probably also remember that sc:field will use the pipeline, whilst sc:fld will not.

OK, on with the code. I’ll show 2 extensions to the renderField pipeline. Both extensions is placed just after the GetFieldValue function:

<renderField>
  <processor type="Sitecore.Pipelines.RenderField.SetParameters, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.RenderField.GetFieldValue, Sitecore.Kernel" />
  <!-- My code -->
  <processor type="PT.Prototype.GetFallbackValue, PT.Prototype" />
  <!-- end:My code -->
  <processor type="Sitecore.Pipelines.RenderField.ExpandLinks, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.RenderField.GetImageFieldValue, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.RenderField.GetLinkFieldValue, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.RenderField.GetInternalLinkFieldValue, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.RenderField.GetMemoFieldValue, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.RenderField.GetDateFieldValue, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.RenderField.GetDocxFieldValue, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.RenderField.AddBeforeAndAfterValues, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.RenderField.RenderWebEditing, Sitecore.Kernel" />
</renderField>

The GetFieldValue processor grabs the contents from the Sitecore field, and I add my step hereafter because I wish to modify the value before it’s rendered to the frontend.

My first processor: Creating language fallback. Sitecore does not have a fallback language mechanism, and some even advocate that it’s a bad idea. Let’s assume that the desicion has been made to use a fallback language, and all we need is to implement it. It’s very simple: Check to see if the GetFieldValue has grabbed a value. If not, grab a value from another language:

using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Pipelines.RenderField;

namespace PT.Prototype
{
  public class GetFallbackValue
  {
    public void Process(RenderFieldArgs args)
    {
      Assert.ArgumentNotNull(args, "args");
      if (args.Result.FirstPart == string.Empty && Sitecore.Context.Site.DisplayMode != Sitecore.Sites.DisplayMode.Edit)
        args.Result.FirstPart = FallbackValue(args.Item, args.FieldName.ToLower(), "en");
    }

    private string FallbackValue(Item item, string fieldName, string fallbackLanguage)
    {
      Item fallbackItem = item.Database.GetItem(item.ID, Sitecore.Globalization.Language.Parse(fallbackLanguage));
      return fallbackItem[fieldName];
    }
  }
}

Did you notice how I check to see if we are in Web Edit mode? If running in web edit mode, I do not fall back, allowing users to see untranslated fields.

OK let’s go to another processor. The field fallback processor. Imagine that you have provided the user with a “Title” field and a “Menu Title” field. If the “Menu Title” is empty you should display the “Title” value. This can be achieved using advanced Inversion Of Control mechanisms, or you can write a couple of lines in the RenderField pipeline:

using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Pipelines.RenderField;

namespace PT.Prototype
{
  public class GetFallbackValue
  {
    public void Process(RenderFieldArgs args)
    {
      Assert.ArgumentNotNull(args, "args");
      if (Sitecore.Context.Site.DisplayMode == Sitecore.Sites.DisplayMode.Edit)
        return;
      if (args.Item.Template.Key == "sample item")
      {
        if (args.FieldName.ToLower() == "menu title" && args.Result.FirstPart == string.Empty)
          args.Result.FirstPart = args.Item["title"];
      }
    }
  }
}
Advertisements

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in c#, Sitecore 6 and tagged , , , , . Bookmark the permalink.

3 Responses to Creating fallback values using the RenderField pipeline

  1. Alex Shyba says:

    Hey Brian,

    Great post! That’s definitely a valid approach and I’ve been playing with the renderField pipeline myself. I’ve found, however, that it is a bit resource intensive, plus such operations as item[“title”] would not work for the fallback.

    Thus, I’ve experimented with a bit different approach by extending the StandardValues Provider. The great thing about SV based approach is that it is field based (very granular) and also supports caching which helps significantly with the performance.

    Check it out on Shared Source:
    http://trac.sitecore.net/LanguageFallback/browser/Trunk/Sitecore.SharedSource.PartialLanguageFallback

    Here is a screencast too:
    http://sitecoreblog.alexshyba.com/2010/11/approaching-language-fallback-with.html

  2. briancaos says:

    I always liked your language fallback solution, which probably is the one to prefer.
    The item[“title”] I use in the field fallback works fine, at least for simple types. Advanced types as the Rich Text Field or the DocX field might need a little more work in some situations.

  3. Neil says:

    Thanks this has been very helpful for me while learning Sitecore and pipelines. Its the only really simple and thorough explanation I could find online. So thanks again :)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s