LibrarySites.Banner

Partial Language Fallback and Glass Mapper V3

I recently found yet another reason to blog about Alex Shyba's Partial Language Fallback Module.  This time, it resulted from an MVC Sitecore application we are building that leverages Glass Mapper.

Within this application, I wanted to play around with Enforcing and Un-Enforcing Language Version presence.  I thought it could be beneficial from both a publishing and indexing perspective if I tried to slim down how many language versions I would need on certain type items (think configuration items, etc.).  I've been using the partial language fallback module for years and knew it still worked fine with Sitecore 7.  So you could imagine my shock and momentary moment of panic when I went to load up my site in a non-default language and have several items that I retrieve via Glass Mapper throw null errors, even though version presence was NOT enabled for them.

I turned to the trusted Google machine and quickly found that others had already run into this situation

Dan Sinclair asks about what is going on here.  Luckily for us, Mike Edwards, a developer of the Glass.Sitecore.Mapper project supplied exactly why this is happening and what to do to get around it.

His reasoning makes a lot of sense:

"If you ask for a Sitecore item that doesn't exist in that particular language, it returns an item with no versions. This means we have to do this check, because otherwise Glass would end up returning empty class which I don't think makes much sense."

This is exactly what happens, UNLESS some form of language fallback has been added to your application.  But since Language Fallback doesn't come out of the box with Sitecore yet (maybe someday??), it would not be practical or even possible to add support for it to Glass Mapper for Sitecore out of the box either.

The steps to make this work are rather simple.  Mike's steps are slightly different from mine, as he describes how to check for fallback assuming you are using the Fallback Item module.  I use the Partial Language Fallback module for field level fallback and therefore I had to tweak it slightly.  I'll explain where that tweak came in below.

1.       Disable Version Count in Global.asax.cs (it will be checked later in the Object Construction Pipeline)

protected void Application_BeginRequest()

{

    Sitecore.Context.Items["Disable"] = new VersionCountDisabler();

}

2.       Create a new class named FallbackCheckTask, you will be registering it the GlassMapperScCustom class in the next step

                using Glass.Mapper.Pipelines.ObjectConstruction;

                using Glass.Mapper.Sc;

                using System;

                using System.Collections.Generic;

                using System.Linq;

                using System.Web;

                using Sitecore.Data.Managers;

                using Sitecore.Data.Items;

                using Sitecore.SharedSource.PartialLanguageFallback.Extensions;

               

                namespace yoursite._Classes.Shared.Customizations.Customized_Glass

                {

                    public class FallbackCheckTask : IObjectConstructionTask

                    {

                        public void Execute(ObjectConstructionArgs args)

                        {

                            if (args.Result == null)

                            {

                                var scContext = args.AbstractTypeCreationContext as SitecoreTypeCreationContext;

               

                                // if the item itself is null, regardless of version, abort

                                if (scContext.Item == null)

                                {

                                    args.AbortPipeline();

                                    return;

                                }

               

                                // NOTE, this is the code I removed, that is specific to the 'OTHER' fallback module (at an item level)

                                //this checks to see if the item was created by the fallback module

if (scContext.Item is Sitecore.Data.Managers.StubItem)

{

                                return;

}

                               

                               

                                // we could be trying to convert rendering parameters to a glass model, and if so, just return.

                                if (String.Compare(scContext.Item.Paths.FullPath, "[orphan]/renderingParameters", true) == 0)

                                {

                                    return;

                                }

               

                                // NOTE, THIS IS THE CODE I CHANGED TO USE THE EXTENSIONS AVAILABLE FROM PARTIAL LANGUAGE FALLBACK

                                // the default glassmapper code would simply abort pipeline if the context items version count for the current langauge was 0

                                // but this does not take item fallback into account

                                // added here a check on the fallback extension method GetFallbackItem, recursively (for chained fallback)

                                // and then if that fallback item is null or it's version count is 0 (and only then) would you go ahead and abort the pipeline

                                if (scContext.Item.Versions.Count == 0)

                                {

                                    var fallBackItem = CheckRecursivelyForFallbackItem(scContext.Item);

                                    if (fallBackItem == null)

                                        args.AbortPipeline();

                                    else if (fallBackItem.Versions.Count == 0)

                                        args.AbortPipeline();

                                    return;

                                }

                            }

                        }

               

                        // in the case of chained fallback, eg fr-CA -> en-CA -> en

                        // could be that the middle languages don't have versions either, but DO have a fallback item

                        // therefore, must check back further until either a version is found, or there are no more fallback items

                        private Item CheckRecursivelyForFallbackItem(Item thisItem)

                        {

                            var fallBackItem = thisItem.GetFallbackItem();

                            if (fallBackItem != null)

                            {

                                if (fallBackItem.Versions.Count == 0)

                                    fallBackItem = CheckRecursivelyForFallbackItem(fallBackItem);

                            }

                            return fallBackItem;

                        }

                    }

                }

3.       Register the new task in GlassMapperScCustom class.

  1. This should already be in your MVC project in the App_Start folder.  The CastleConfig method should already be in there, you just have to add the 'container.register' line.

                                public static void CastleConfig(IWindsorContainer container){

                                                var config = new Config();

                                                // must check FallbackItem in the FallbackCheckTask before determining to abort the glass process of getting the item

                                                container.Register(Component.For<IObjectConstructionTask>().ImplementedBy<FallbackCheckTask>().LifestyleTransient() );

                                                container.Install(new SitecoreInstaller(config));

                                }

And that's it.  Glass will not consider the item null and assuming you have fallback enabled correctly for the site, field, etc., the Partial Language Fallback framework will take care of the rest.

Much thanks to both Dan Sinclair for asking the right questions and Mike Edwards for giving a great answer!

If you are looking for more information about configuring the Partial Language Fallback module, please see my other posts.

You can download the code files mentioned here from Git:

https://github.com/Verndale-Corp/Sitecore-Fallback-GlassMapper