Field level fallback is not working in template inheritance

An issue regarding the field level fallback language in Sitecore 8.1 update 1. We need to enable field level fallback for all the fields of all the template. While working on that we found that field level fallback is not working in inheritance. i.e. if you enable field level fallback in Template Field’s standard value (/sitecore/templates/System/Templates/Template field/__Standard Values), then it should get enabled for all the fields. But unfortunately it is not.

 

Following are the steps to reproduce the issue:

  1. In the Sample Item, on Title Field I have enabled field level fallback. and when I create the pt-BRversion of the home item, the field level fallback works perfectly as expected.

EnableFieldLevelFallback

EnableFieldLevelFallback2

  1. But we have lot many template and lot many fields. So what I have tried is  instead of enabling field level fallback on individual fields, I have enabled it on theStandard valuesof Template field (/sitecore/templates/System/Templates/Template field/__Standard Values) so that all fields have that fallback enabled.

EnableFieldLevelFallback3

 

  1. So, after resetting the Title Field, the value of Enable field level fallback is now taking value from the standard values of theTemplate Field template.

 

EnableFieldLevelFallback4

 

  1. Now when I am creating the Portuguese version of the same item, as per the field level fallback it should show the value of en version but unfortunately it is not showing it.

EnableFieldLevelFallback5

So in short, if we enable the Enable Field level fallback for individual fields, it is working fine but if we enable it from Template Field’s standard value (in inheritance), though it display as marked in field, it is not working.

 

Reason:

There is a issue in IsValidForLanguageFallback processor of getFieldValue pipeline.

 

IsValidForLangaugeFallback processor has Process method which calls the LanguageFallbackFieldValuesManager’s IsValidForFallback method and it calls the IsValidForFallback method of LanguageFallbackFieldValuesProvider and the issue resides in this method.

public virtual bool IsValidForFallback(Field field)
{
	SiteContext context;
	bool? currentValue = Switcher<bool?, LanguageFallbackFieldSwitcher>.CurrentValue;
	if (currentValue == false)
	{
		return false;
	}
	if ((currentValue != true) && (((context = Context.Site) == null) || !context.SiteInfo.EnableFieldLanguageFallback))
	{
		return false;
	}
	bool flag = true;
	Item item = field.Item;
	string key = string.Concat(new object[] { field.Database.Name, item.ID, field.ID, field.Language.Name });
	object obj2 = field.Database.Caches.IsLanguageFallbackValidCache.GetValue(key);
	if (obj2 != null)
	{
		return (((string) obj2) == "1");
	}
	Language language = LanguageFallbackManager.GetFallbackLanguage(item.Language, item.Database, item.ID);
	if ((language == null) || string.IsNullOrEmpty(language.Name))
	{
		flag = false;
	}
	else if (field.Name.StartsWith("__"))
	{
		flag = false;
	}
	else if (field.Shared)
	{
		flag = false;
	}
	else if (StandardValuesManager.IsStandardValuesHolder(item))
	{
		flag = false;
	}
	else if ((field.ID == FieldIDs.EnableLanguageFallback) || (field.ID == FieldIDs.EnableSharedLanguageFallback))
	{
		flag = false;
	}
	else if (!field.SharedLanguageFallbackEnabled)
	{
		if (Settings.LanguageFallback.AllowVaryFallbackSettingsPerLanguage)
		{
			Item innerItem;
			using (new LanguageFallbackItemSwitcher(false))
			{
				innerItem = field.InnerItem;
			}
			if ((innerItem == null) || (innerItem.Fields[FieldIDs.EnableLanguageFallback].GetValue(false, false) != "1"))
			{
				flag = false;
			}
		}
		else
		{
			flag = false;
		}
	}
	field.Database.Caches.IsLanguageFallbackValidCache.Add(key, flag ? "1" : "0");
	return flag;
}

In the last section of else if, it checks for if sharedLanguageFallback is not enabled. In our case it is not enabled so, the debugger comes into that condition, then it checks for if AllowvaryFallbackSettingsperLanguage is true or not. In our case it is not so debugger comes into else and in else there is no code/Condition it is just set flag to false and IsValidForFallback always return false which should not.

 

Support ticket had been raised for the same and sitecore found that it is a bug. They have provided a updated dll and config for the same. In the dll’s code we found the following difference in the last else if block.

else if (!field.SharedLanguageFallbackEnabled)
{
	if (Settings.LanguageFallback.AllowVaryFallbackSettingsPerLanguage)
	{
		Item innerItem;
		using (new LanguageFallbackItemSwitcher(false))
		{
			innerItem = field.InnerItem;
		}
		if ((innerItem == null) || (innerItem.Fields[FieldIDs.EnableLanguageFallback].GetValue(false, false) != "1"))
		{
			flag = false;
		}
	}
	else
	{
		Item item3;
		using (new LanguageFallbackItemSwitcher(false))
		{
			item3 = field.InnerItem;
		}
		if ((item3 == null) || (item3.Fields[FieldIDs.EnableSharedLanguageFallback].GetValue(true, false) != "1"))
		{
			flag = false;
		}
	}
}

If field.SharedLanguageFallbackEnabled is false and AllowVaryFallbackSettingPerLanguage is also false then it comes to the highlighted else section.

Here, field item is set and then GetValue method is called for its EnabledSharedLanguageFallback (EnabledSharedLanguage refers to Field Level Fallback property) property with (true,false) parameter. The magic is here in the passing the parameter.  That’s it. And the other code is same as it is.  So what happening in GetVaue method is:

 

This GetValue(true,false) actally calls the method Sitecore.Data.Fields.Field.GetValue(bool allowStandardValue, bool allowDefaultValue) .

 

From this method a call is made to GetValue(bool allowStandardValue, bool allowDefaultValue, bool allowFallbackValue)  with the parameter true, false ,true:  .GetValue(true, false , true)

 

This method calls GetValue(bool allowStandardValue, bool allowDefaultValue, bool allowFallbackValue, allowInheritValue) with param true, false, true, true:GetValue(true, false , true,true)

 

And from this method the last overloaded method called:  GetValue(bool allowStandardValue, bool allowDefaultValue, bool allowFallbackValue, bool allowInheritValue, bool allowInnerValue)  with parameter true,false,true,true,true: GetValue(true, false , true,true,true)

 

And in this method, the GetFieldValueArgs are assigned and hence for the AllowFallbackValue  is set to true

 

GetFieldValueArgs args = new GetFieldValueArgs {
	Field = this,
	AllowStandardValue = allowStandardValue,
	AllowDefaultValue = allowDefaultValue,
	AllowFallbackValue = allowFallbackValue,
	AllowInheritValue = allowInheritValue
};
CorePipeline.Run("getFieldValue", args);
this.containsStandardValue = args.ContainsStandardValue ? 1 : 0;
this.inheritsValueFromOriginalItem = args.InheritsValueFromOriginalItem ? 1 : 0;
this.containsFallbackValue = args.ContainsFallbackValue ? 1 : 0;
this.fallbackValueSource = args.FallbackSource;
return args.Value;

And finally IsValidForFallback method returns true. And now the things are working fine.

Field level fallback is now working fine for inherited value as well.

Patch provided by Sitecore Support:

Sitecore Support provides following patch files which can solve the issue: a config and a dll file

Download the files and

1. Place the  Sitecore.Support.105327.dll assembly into your /bin folder.
2. Place the Sitecore.Support.105327.config file into your /App_Config/Include folder.

Happy Coding 🙂

Advertisements

3 comments

  1. Pingback: Sitecore field level fallback not working with template inheritance – Sitecore.Blog()

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