I guess I somewhat know the answer, but I'd like to get the community feedback on this.

What is the correct way of identifying where a field value originates from? When item.Fields[field].HasValue is false, the Value property contains a fallback value. I want to know what kind of fallback value it is. Is it the default value (the shared field on the template field item), is it from __Standard values, is it a language fallback value or is it from a clone source item?

The Field object has properties indicating this, such as ContainsStandardValue, ContainsFallbackValue, InheritsValueFromOriginalItem, IsValidForLanguageFallback and so on. Now, it turns out that those properties are actually modified when you call the field.GetValue() methods, and their values becomes different depending on what argument you pass to the field.GetValue(bool allowStandardValue, bool allowDefaultValue, bool allowFallbackValue, bool allowInheritValue, bool allowInnerValue) (or any of its shorter alternatives). This feels like an error in the implementation to me.

Is there a more solid, reliable or preferred way of getting this information, other than always calling field.GetValue(true, false, true) prior reading any of those fallback properties on the field?

Update: As Mark pointed out in the comments, the issue here is that the properties "remember" the states of the last GetValue call. Here's a sample to illustrate this:

Let's say there is an item with a Title-field, with a null value, so the shown value is taken from __Standard values:

var field = item.Fields["Title"];
var title = field.Value;
var stdValue = field.ContainsStandardValue; // becomes true

title = field.GetValue(false);
stdValue = field.ContainsStandardValue; // now becomes false

So, the value of these properties are based on the last call to GetValue(), that could be code from another processor etc.

  • Why does it feel like an error in implementation to you? The idea behind this abstraction is to shield developers/implementers from HOW a field fallback value comes to be, without breaking the basic item/field API code. A secondary objective is to be able to display help information in the Content Editor ([shared - standard value] and so on).
    – Mark Cassidy
    Jun 1, 2021 at 8:54
  • Yes, this is what I thought the intention was as well. But in my opinion it breaks. Let's say I have a field containing a standard value, and I read the field.ContainsStandardValue property, it'd expect it to be true. And it usually is. But if some other code, such as another processor, has called field.GetValue(false) prior my code, the property would read false. So the values of those properties are inconsistent.
    – mikaelnet
    Jun 1, 2021 at 9:08
  • 1
    Ah really? now I get what you mean. So an item - once instantiated will "remember" how its field values came to be and it will persist until you execute a GetField with alternative flags. That it?
    – Mark Cassidy
    Jun 1, 2021 at 9:16
  • Exactly! I guess it's for caching purposes, but I think it should only cache those values given that the GetValue() method is called with the expected arguments.
    – mikaelnet
    Jun 1, 2021 at 9:20


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.