6

We just updated our project to use Glass.Mapper V3. We LOVE it. But we've encountered an issue. It doesn't seem to respect language fallback.

We have our site set up so that if a user picks a non-default language, they will see the item of that language if it exists. If not, they will see the default ("fallback") language version. We have also set this up at the field level, so that if there is a non-default version of an item but not all the fields are changed, any unchanged fields will fall back to the default language version's value for that field.

Is there anything we can do to enable Glass to use language fallback?

Dan Sinclair
  • 907
  • 1
  • 9
  • 27
  • Which language fallback module are you using? The Partial Language Fallback module uses a standard values provider, so it should work with Glass without a problem. I have never used the Fallback Language Item Provider, so I'm not so sure about that one. – Ben Golden Oct 30 '13 at 20:25
  • And is it PLF that's failing, or just the item/version-level fallback? – nickwesselman Oct 30 '13 at 20:59
  • We're using both the Partial Language Fallback (field-level) and the Fallback Language Item Provider (item-level) modules. When I try to get a language version of an item that doesn't exist (try to get "es" when only "en" exists), I get null. If there is an "es" item but some fields are unchanged (falling back to the "en" version), they appear empty when accessed from Glass. – Dan Sinclair Oct 30 '13 at 23:56
  • Dan, can you email me more details of what you are trying to do? In theory Glass should work because it just wraps the Sitecore item API, i.e. anything that happens behind an item, e.g. the fallback module, should still work. – Michael Edwards Oct 31 '13 at 08:04
  • @techphoria414, I stand corrected. Only the Fallback Language Item Provider module is not working. Upon further investigation, it is returning values from the field-level fallback, but when fields are lists of items, there are no items in the list (because item-level fallback doesn't get them). – Dan Sinclair Oct 31 '13 at 15:04
  • @MichaelEdwards It looks to be related to this: https://groups.google.com/d/msg/glasssitecoremapper/giWIWqlGFS0/zsYGKc4IMFIJ. When I check the item in my code (before calling item.GlassCast()), item.Versions.Count is 0. Looking at your source for SitecoreService.cs, it looks like that check is invalidating it. https://github.com/mikeedwards83/Glass.Mapper/blob/master/Source/Glass.Mapper.Sc/SitecoreService.cs#L349. Thoughts or recommendations? – Dan Sinclair Oct 31 '13 at 15:20

2 Answers2

6

I am updating this with a bit of background on why we do the check. If you ask for a Sitecore item that doesn't exist you get a null value, so that is simple to handle. However if you ask for a Sitecore item that doesn't exist in that particular language 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 answer will get a little experimental.

First in the the Spherical.cs file you need to disable the check:

protected void Application_BeginRequest()
{
    Sitecore.Context.Items["Disable"] = new VersionCountDisabler();
}

We can then move the check to later on to the Object Construction pipeline. First create a task:

public class FallbackCheckTask : IObjectConstructionTask
{
    public void Execute(ObjectConstructionArgs args)
    {
        if (args.Result == null)
        {
            var scContext = args.AbstractTypeCreationContext as SitecoreTypeCreationContext;
            if (scContext.Item == null)
            {
                args.AbortPipeline();
                return;
            }    
            //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;
            }

            if (scContext.Item.Versions.Count == 0)
            {
                args.AbortPipeline();
                return;
            }
        }
    }
}

Then finally register this task in the GlassMapperScCustom class:

    public static void CastleConfig(IWindsorContainer container){
        var config = new Config();

        container.Register(
            Component.For<IObjectConstructionTask>().ImplementedBy<FallbackCheckTask>().LifestyleTransient()
            );
        container.Install(new SitecoreInstaller(config));
    }

I haven't tested this but it should in theory work <- disclaimer ;-)

ale
  • 6,369
  • 7
  • 55
  • 65
Michael Edwards
  • 6,308
  • 6
  • 44
  • 75
  • Well, Mike Edwards strikes again. It works exactly as described. I considered adding a check to see if the current site had fallback enabled, but decided that it was an unnecessary performance hit since the code will still work whether fallback is enabled or not. Great work and thanks again, Mike. – Dan Sinclair Nov 01 '13 at 14:53
  • Rendering Parameter items don't have versions, so this code aborts the pipeline prematurely when trying to use GetParameters in a control (from this tutorial http://glass.lu/docs/tutorial/sitecore/tutorial23/tutorial23.html). We need to place a check above the second AbortPipeline call to make sure scContext.Item is not a 'renderingParameters' item. – Sean Holmesby Nov 20 '13 at 20:56
  • Has anyone implemented this in Sitecore 7.2 with MVC fine? Unless a version is created for the language, no item seems to be getting returned. However, this only appears to be when using Sitecore Query + Glass, perhaps this is a separate issue? – Kasaku Oct 23 '14 at 15:01
  • @PirateKitten Can you log your issue on GitHub and I will take a look. – Michael Edwards Oct 27 '14 at 16:47
1

There are few potential issues with provided solution when sitecore 7 (7.2) + IoC + solr + mvc is used.

When using IoC ex Winsdor please make sure that your Global.asax looks like this one <%@ Application Codebehind="Global.asax.cs" Inherits="Sitecore.ContentSearch.SolrProvider.CastleWindsorIntegration.WindsorApplication" Language="C#" %>. Once, by mistake this file has been changed to <%@ Application Codebehind="Global.asax.cs" Inherits="Merck.Manuals.Web.Global" Language="C#" %> and language fallback was not working. Also the errors we were getting wasn't descriptive as we thought that solr schema is incorrect.

Code Sitecore.Context.Items["Disable"] = new VersionCountDisabler(); can be added to PreprocessRequestProcessor and it works fine which is better solution that modifying global.asax.