Newtonsoft.Json.JsonSerializationException: Error setting value to 'StringProperty' on 'MyComponent' with inner ArgumentNullException

249 views Asked by At

I'm attempting to create a 'Has Been Edited' tracker for my component classes, like this:

public class MyComponent : ObservableObject
{
    // If any changes are made to properties that have the InspectableAttribute, this becomes true.
    public bool HasBeenEdited
    {
        get => _hasBeenEdited;
        protected set
        {
            if (value == _hasBeenEdited)
            {
                return;
            }
            _hasBeenEdited = value;
        }
    }
    private bool _hasBeenEdited = false;

    [Inspectable]
    public string StringProperty
    {
        get => _stringProperty;
        set => SetProperty(ref _stringProperty, value);
    }
    private string _stringProperty = null;

    protected override void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyInfo propertyInfo = GetType().GetProperty(e.PropertyName);
        if (Attribute.IsDefined(propertyInfo, typeof(InspectableAttribute)))
        {
            HasBeenEdited = true;
        }
        base.OnPropertyChanged(e);
    }
}

However, now that I'm testing it, when my 'MyComponent' instances are being deserialised from Json, I get the following unhelpful exception:

Newtonsoft.Json.JsonSerializationException: Error setting value to 'StringProperty' on 'MyComponent'. Inner Exception: ArgumentNullException: Value cannot be null. Arg_ParamName_Name This exception was originally thrown at this call stack: System.Attribute.IsDefined(System.Reflection.MemberInfo, System.Type, bool) System.Attribute.IsDefined(System.Reflection.MemberInfo, System.Type) MyComponent.OnPropertyChanged(System.ComponentModel.PropertyChangedEventArgs) in MyComponent.cs ...

First of all, the error is obviously a bit typo'd. I'm not seeing a property to 'StringProperty'. I'm setting a property named StringProperty. But I doubt that's a real problem.

Second, this value can safely be set to null, and is in fact initialised as null.

When I remove the call to Attribute.IsDefined the issue stops, suggesting that's somehow the problem, but it's not clear how.

1

There are 1 answers

0
Thomas Slade On

Figured this out.

The issue actually came from a location where I was setting a property incorrectly:

public class MyKeyedComponent : MyComponent
{
    public string Key
    {
        get =>  _key;
        set => SetKey(value);
    }
    private string _key;
    
    public void SetKey(string value)
    {
        SetProperty(ref _key, value);
        
        // Do other stuff after setting the key
    }
}

SetProperty uses the calling member as its third parameter (the propertyName) unless otherwise specified. I'm so used to calling SetProperty from within the actual property setter, that I forgot to do otherwise here.

As a result, my OnPropertyChanged override was intercepting the changing of a property named SetKey. That is a function, and no such property exists.

As mentioned in another comment, my difficulty debugging this was partly due to me building release rather than debug.